Элементарно. Грязь и окисление контактов. Ну и "пропил" конечно же. Разобрать, зачистить и будет "как новый". или правильный кондер, точнее "НЧ фильтр". :)
Элементарно. Грязь и окисление контактов. Ну и "пропил" конечно же. Разобрать, зачистить и будет "как новый". или правильный кондер, точнее "НЧ фильтр". :)
отсюда вывод: на скоростные балалайки ставим оптические энкодеры, на медленные - механику.
*интересно, нарыть полный даташит на механический энкодер и прочитать рекомендуемую производителем максимальную скорость вращения вала энкодера, рекомендуемую схему подключения, что бы прекратить заниматься извращениями.
**рекомендацию тестировать код на убитом энкодере считаю странной.
Я вообще слабо понимаю проблему. Вроде как не гипермассовое производство (для себя любимого, ну на крайняк ещё для 10-100 таких же, кто купит и то "может быть"), чтобы экономить на оптическом энкодере, который либо собирается из 2-х деталек по 3 коп. за ведро, или они же выдираются из старых мышек, коих "завались" на любом офисе. Подойди к любому эникейщику, он тебе этих сдохших мышей прямо в ведро и отсыплет. Себе так наковырял рабочих переключательных кнопок штук 30 для "датчиков касания" (в Лего исполнении продаются по .. 1500руб/шт!) и пар светодиод-транзистор с дырчатыми колесиками .. нафига вообще в наше время нужны эти "скользящие трещётки"?
Кстати, писал уже про китайские 130-е моторы с оптическими энкодерами на валу .. Ардуино мега вполне справляется с подсчетом скорости вращения 8000rpm по прерываниям (фронт/срез) как миниум 2-х моторов одновременно. Покупал по $1/шт .. вместе с мотором вот, в конце сентября 2015 и пришли.
Мой вариант обработчика энкодера. Очень простой и совершенно безглючен. Обработчик сидит в теле внешнего прерывания PCINT. В нижеследующем скетче задействованы входы A0 и A1 как цифровые. Используется подтяжка к питанию (распаянная на платке стандартного энкодера), и антидребезговые конденсаторы 0,1мкф на землю. Кому нужно на другие ноги - смотреть даташит страница 73 и маскировку битов сделать по аналогии.
volatile int enc;
void setup() {
Serial.begin(9600);
PCICR=1<<PCIE1; //разрешить пренрывание
PCMSK1=(1<<PCINT9)|(1<<PCINT8); //выбрать входы
}
ISR (PCINT1_vect){
static byte old_n=PINC&3; // маска B00000011 что б читать только нужные 2 бита
byte new_n=PINC&3;
if (old_n==1&&new_n==3||old_n==2&&new_n==0) {enc++;}
if (old_n==2&&new_n==3||old_n==1&&new_n==0) {enc--;}
old_n= new_n;
}
void loop() {
Serial.println(enc);
}
dimax Если не затруднит, расскажите пожалуйста по коду. Только начал осваивать arduino очень многое непонятно. С этим кодом мой энкодер прекрасно работает только в сторону увеличения, в сторону уменьшения никак не хочет. Подскажите пожалуйста в чем может быть проблема. И еще один маленький вопрос, как ограничить максимальное значение переменной enc например до 50 и минимальное до 0. Извините за глупые вопросы, только учусь.
ii_alex, я потом ещё упростил обработчик энкодера, вот последний вариант (для входов A0 и A1):
volatile int enc;
void setup() {
Serial.begin(9600);
PCICR=1<<PCIE1; //разрешить прерывание
PCMSK1=1<<PCINT8; //выбрать вход на котором сработает прерывание
}
ISR (PCINT1_vect){
byte n=PINC&3; // узнать значение суммы битов PC0 и PС1
if (n==1||n==2) {enc++;}
if (n==3||n==0) {enc--;}
}
void loop() {
Serial.println(enc);
}
По коду что сказать? Тут всё базируется на прерывании PCINT и двоичной математике. Читается порт, если его младшие биты в сумме своих весов дают те значения, что указаны в скетче то делается вывод, что энкодер крутили в ту или другую сторону. Для этого способа обязательно нужны конденсаторы на землю от обоих выводов энкодера. Ёмкость зависит от конкретного энкодера, 0,1мкф у меня нужно было на очень старом, убитом энкодере. На новом достаточно будет 0,001мкф. Если в одну сторону инкременируется, а в другую нет, то скорее всего недостаточная ёмкость конденсатора. Или его вообще нет :) И подтяжка к питанию на плате энкодера конечно должна быть.
Версия с ограничением от 0 до 50. В первой строке начальное значение.
dimax Спасибо за ответ ! Пытаюсь вникать. Энкодер обычный, резики подтяжки распаяны, конденсаторы стоят на 0,1 мкф. Если залить ваш скетч из соседней ветки, где обсуждается (отличная вешь, генератор). То энкодер работает без проблем, в любую сторону. Значит подключение A0 A1, емкости, резисторы, все в порядке. А с эти скетчем нивкакую в сторону уменьшения. Последний, который самый упрощенный, к сожалению смогу попробовать только завтра. А так хочется !
Значит подключено к другим выводам (скорее всего к PC1 и PC2). А в варианте выше - PC0 и PC1.
Только вот совершенно не понятно, зачем ещё условие n==1. Ибо оно может только навредить, т.к. будет читаться ещё и значение с соседнего вывода (PC0).
Кстати, если в обработчик добавить обработку времени, например на пару ms, то кондёры из схемы можно смело выкидывать.
Как верно подметил Alexino так работать вообще не должно. Обратите внимание, при считанной единице с порта получается и enc+ и enc -, а это абсурд. Если у вас работает, значит читаются только 4 или 6, и скорее всего значения меняются не каждый раз, а через один щелчок. В оригинале было 4-2 6-0.
Alexino пишет:
Кстати, если в обработчик добавить обработку времени, например на пару ms, то кондёры из схемы можно смело выкидывать.
Хоть это и нарушение идеологии прерываний, но как нибудь проверю такой вариант из спортивного интереса:)
Хоть это и нарушение идеологии прерываний, но как нибудь проверю такой вариант из спортивного интереса:)
Можно же это всё сделать и без нарушений :)
Существует системный таймер, который можно читать с помощью millis(). Думаю, об этом Вы в курсе. Ну а дальше дело техники )
Причём, я не зря назвал цифру 2, т.к. при использовании системного таймера, разница в 1 мс = 0...1 мс, и можно нарваться на самое минимально время, при котором дребезг будет учтён.
А при отслеживании разницы в 2 мс., мы гарантированно отсеиваем целую миллисекунду. А диапазон времён будет = 1...2 мс.
dimax в оригинале действительно 4-2 6-0. Только в этом варианте получается, что энкодер срабатывает через 2 значения т.е было 1 вращаем становится 3. Чтобы получить 2 нужно вращать энкодер очень очень медленно и буквально чуть-чуть тогда сработка на 1 если крутить стандартно то обрабатывается 2 значения. Я только учусь по этому экспериментировал. Тот код который выложил работает отлично, все считается по 1 в любую сторону, но код неправильный. Подскажите пожалуйста как правильно обработать.
ii_alex, значит у вас энкодер другого типа. На один физический щелчок он дёргает прерывание 2 раза. В теме про генератор обсуждался такой вариант, почитайте сообщение #52 Можно как вариант убрать одну цифру. if ( n==4) {enc++;} if (n==6) {enc--;}
А мааааааааленькую фотографию энкодэра можно посмотреть?
Или название какое у него имеется?
Может просто с кондёрами переборщили? 1-10 нан - я бы больше не ставил.
ii_alex, Я имел ввиду, что нужно сделать либо как в #52, либо убрать одну цифру. А вы взяли как в 52 + убрали цифру. Но раз второй вариант заработал , то и ладно.
Посмотрите по "полосатым полоскам".
При смене состояния вверх или вниз любого входа ( а это PinChangeInterrupt)
и при 100%, а это главное, отсутствии дребезга ( как раз лечится кондёрчиками, а гистерезис входов нам в этом помогает)
два входа имеют 4 состояния ( потому-что это 2 бита).
И эти состояния будут, как писал dimax: 1,2 или 0,3
if (n==1||n==2) {enc++;}
if (n==3||n==0) {enc--;}
Кстати по поводу кондёрчиков очень важное замечание.
Они заряжаются довольно медленно через резистор привязки,
а вот разряжаются очень быстро через металлический контакт.
Я бы при 20 кОм привязки поставил Ом 510-1000 последовательно на контакты- хоть немного затянуть их разряд.
Досталась панель от неисправной магнитолы, хочу переделать ее для управления чем нибудь другим. Возникла проблема, в ней стоит 3х фазный энкодер вот такой http://www.alps.com/prod/info/E/HTML/Encoder/Ring/EC35AH/EC35AH240403.html Подскажите как его победить, логика работы другая. Пробовал платой нано каждые 10мс опрашивать порты и слать в сериал порт - все видит, но при быстрой прокрутке не успевает. Покупать другую плату где есть больше ног для прерываний? или можно как то по другому?
Решил я значит смастерить термомстат на котел в загородном доме.
котел греется дровами и электричесвом функцианал таков:
при достижении заданой температуры включается насос
обычный термостат для нагревателей
сирена, на случай превышения заданой температуры (на случай, когда увлекся с дровами)
суть проблемы в написании меню установок... вроде что-то написал, но работает как-то корявенько
прошу помощи! ткните что не так! может как-то оптимизировать....
вот код
#include <LiquidCrystal_I2C.h>
#include <RotaryEncoder.h>
RotaryEncoder encoder(12, 13); //устанавливаем 12, 13 порты для энкодера
LiquidCrystal_I2C lcd(0x27,16,2); // определяем дисплей
int encBtn = 11; // кнопка энкодера
int btnPin = 10; // кнопка
int result = -1;
int subRes = -1;
int encBtnCl = 0;
int encBtnSubMenuCl = 0;
int setMenuCl = 0;
long lcdUpdate;
boolean PUMP = false;
boolean HEATER = false;
boolean SERENA = false;
int PUMP_temp;
int HEATER_temp;
int SERENA_temp;
char* indexMenu[] = {
"Setup PUMP",
"Setup HEATER",
"Setup ALARM",
"EXIT Setup"
};
void setup()
{
pinMode(13, INPUT);
pinMode(12, INPUT);
pinMode(11, INPUT);
pinMode(10, INPUT);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.setCursor(2,0);
lcd.print("ENCODER_test");
digitalWrite(encBtn, HIGH); digitalWrite(btnPin, HIGH); digitalWrite(13, HIGH); digitalWrite(12, HIGH);
Serial.begin(9600);
} // setup()
void loop(){
if (digitalRead(btnPin) == LOW){
lcd.clear();
lcd.setCursor(6,0);
lcd.print("MENU");
while (setMenuCl != 1) menu();}else {
lcd.clear();
lcd.setCursor(2,0);
lcd.print("ENCODER_test");
setMenuCl = 0;}
}
void menu(){
/////////////////////////////----МЕНЮ----///////////////////////////////////////////////////////////////////////////
/////////////////////////////ОПРОС ЭНКОДЕРА
static int pos = 0;
encoder.tick();
int newPos = encoder.getPosition();
//_____
if (pos < newPos) result++;// |
if (pos > newPos) result--;// | крутим меню по кругу
if (result > 3) result = 0;// |
if (result < 0) result = 3;// |
//_____
if (pos != newPos){
pos = newPos;
/////////////////////////////// обновление дисплея
if (millis() - lcdUpdate >= 100) {
lcd.clear();
lcd.setCursor(6,0);
lcd.print("MENU");
///////////////////////////ИНДИКАЦИЯ МЕНЮ
switch (result){
case 0: //установка насоса
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
break;
case 1: //установка нагревателя
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
break;
case 2: //установка сирены
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
break;
case 3: //выход
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
break;
}
lcdUpdate = millis();
} // конец обновления
} // конец опроса энкодера
/////////////////////////////////////////////////////КОНЕЦ ИНДИКАЦИИ МЕНЮ
/////////////////////////////////////////////////////ВХОД В ПОДМЕНЮ 1
if ((digitalRead(encBtn) == LOW)&&(result == 0)){ //ОПРОС КНОПКИ ЭНКОДЕРА
//ЕСЛИ КНОПКА НАЖАТА И ПУНКТ МЕНЮ 1, ТО...
lcd.clear();
lcd.setCursor(0,0);
lcd.print(indexMenu[result]);
lcd.setCursor(0,1);
lcd.print("****************");
Serial.print("encoder btn1 ");
Serial.println(encBtnCl);
if (encBtnCl == 0){
while (encBtnCl != 3){
/////////////////////////////////////////////////////ИНДИКАЦИЯ ПОДМЕНЮ НАСОС
encoder.tick();
newPos = encoder.getPosition();
if (pos < newPos) subRes++;
if (pos > newPos) subRes--;
if (subRes > 2) subRes = 0;
if (subRes < 0) subRes = 2;
if (pos != newPos){
pos = newPos;
//////////////////////////////////////////////////////////////////////////////////////////
if (millis() - lcdUpdate >= 100) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(indexMenu[result]);
switch (subRes){
case 0:
lcd.setCursor(0,1);
lcd.print("ON");
break;
case 1:
lcd.setCursor(0,1);
lcd.print("OFF");
break;
case 2:
lcd.setCursor(0,1);
lcd.print("<=Back");
break;
}
lcdUpdate = millis();
}
}
/////////////////////////////////////////////////////КОНЕЦ ИНДИКАЦИИ ПОДМЕНЮ 1
/////////////////////////////////////////////////////СОХРАНЕНИЕ ПАРАМЕТРОВ ИЛИ ВЫХОД
if ((digitalRead(encBtn) == LOW)&&(subRes == 0)){ //ВКЛЮЧИТЬ НАСОС И УСТАНОВИТЬ ТЕМПЕРАТУРУ
/*
encBtnCl = subRes;
Serial.println(encBtnCl);
*/
PUMP = true;
if (encBtnSubMenuCl == 0){
while (encBtnSubMenuCl != 1){
pos = 0;
encoder.tick();
newPos = encoder.getPosition();
if (pos != newPos) {
lcd.setCursor(10, 1);
lcd.print(newPos);
lcd.print(" ");
pos = newPos;
}
}
}}
if ((digitalRead(encBtn) == LOW)&&(subRes == 1)){ //ВЫКЛЮЧИТЬ НАСОС
/*
encBtnCl = subRes;
Serial.println(encBtnCl);
*/
PUMP = false;
}
if ((digitalRead(encBtn) == LOW)&&(subRes == 2)){ //ВЫХОД
lcd.clear();
lcd.setCursor(6,0);
lcd.print("MENU");
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
encBtnCl = 3;
menu();
}
}
///////////////////////////////////////////////////////
encBtnCl = 0;
subRes = -1;
}
}///////////////////////////////////////////----КОНЕЦ ПУНКТА ПОДМЕНЮ 1----////////////////////////
/////////////////////////////////////////////////////ВХОД В ПОДМЕНЮ 2
if ((digitalRead(encBtn) == LOW)&&(result == 1)){ //ОПРОС КНОПКИ ЭНКОДЕРА
//ЕСЛИ КНОПКА НАЖАТА И ПУНКТ МЕНЮ 1, ТО...
lcd.clear();
lcd.setCursor(0,0);
lcd.print(indexMenu[result]);
lcd.setCursor(0,1);
lcd.print("****************");
Serial.print("encoder btn1 ");
Serial.println(encBtnCl);
if (encBtnCl == 0){
while (encBtnCl != 3){
/////////////////////////////////////////////////////ИНДИКАЦИЯ ПОДМЕНЮ НАГРЕВАТЕЛЬ
encoder.tick();
newPos = encoder.getPosition();
if (pos < newPos) subRes++;
if (pos > newPos) subRes--;
if (subRes > 2) subRes = 0;
if (subRes < 0) subRes = 2;
if (pos != newPos){
pos = newPos;
//////////////////////////////////////////////////////////////////////////////////////////
if (millis() - lcdUpdate >= 100) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(indexMenu[result]);
switch (subRes){
case 0:
lcd.setCursor(0,1);
lcd.print("ON");
break;
case 1:
lcd.setCursor(0,1);
lcd.print("OFF");
break;
case 2:
lcd.setCursor(0,1);
lcd.print("<=Back");
break;
}
lcdUpdate = millis();
}
}
/////////////////////////////////////////////////////КОНЕЦ ИНДИКАЦИИ ПОДМЕНЮ 2
/////////////////////////////////////////////////////СОХРАНЕНИЕ ПАРАМЕТРОВ ИЛИ ВЫХОД
if ((digitalRead(encBtn) == LOW)&&(subRes == 0)){ //ВКЛЮЧИТЬ НАГРЕВАТЕЛЬ И УСТАНОВИТЬ ТЕМПЕРАТУРУ
/*
encBtnCl = subRes;
Serial.println(encBtnCl);
*/
}
if ((digitalRead(encBtn) == LOW)&&(subRes == 1)){ //ВЫКЛЮЧИТЬ НАГРЕВАТЕЛЬ
/*
encBtnCl = subRes;
Serial.println(encBtnCl);
*/
}
if ((digitalRead(encBtn) == LOW)&&(subRes == 2)){ //ВЫХОД
lcd.clear();
lcd.setCursor(6,0);
lcd.print("MENU");
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
encBtnCl = 3;
menu();
}
}
///////////////////////////////////////////////////////
encBtnCl = 0;
subRes = -1;
}
}///////////////////////////////////////////----КОНЕЦ ПУНКТА ПОДМЕНЮ 2----////////////////////////
/////////////////////////////////////////////////////ВХОД В ПОДМЕНЮ 3
if ((digitalRead(encBtn) == LOW)&&(result == 2)){ //ОПРОС КНОПКИ ЭНКОДЕРА
//ЕСЛИ КНОПКА НАЖАТА И ПУНКТ МЕНЮ 1, ТО...
lcd.clear();
lcd.setCursor(0,0);
lcd.print(indexMenu[result]);
lcd.setCursor(0,1);
lcd.print("****************");
Serial.print("encoder btn1 ");
Serial.println(encBtnCl);
if (encBtnCl == 0){
while (encBtnCl != 3){
/////////////////////////////////////////////////////ИНДИКАЦИЯ ПОДМЕНЮ СИРЕНА
encoder.tick();
newPos = encoder.getPosition();
if (pos < newPos) subRes++;
if (pos > newPos) subRes--;
if (subRes > 2) subRes = 0;
if (subRes < 0) subRes = 2;
if (pos != newPos){
pos = newPos;
//////////////////////////////////////////////////////////////////////////////////////////
if (millis() - lcdUpdate >= 100) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(indexMenu[result]);
switch (subRes){
case 0:
lcd.setCursor(0,1);
lcd.print("ON");
break;
case 1:
lcd.setCursor(0,1);
lcd.print("OFF");
break;
case 2:
lcd.setCursor(0,1);
lcd.print("<=Back");
break;
}
lcdUpdate = millis();
}
}
/////////////////////////////////////////////////////КОНЕЦ ИНДИКАЦИИ ПОДМЕНЮ 3
/////////////////////////////////////////////////////СОХРАНЕНИЕ ПАРАМЕТРОВ ИЛИ ВЫХОД
if ((digitalRead(encBtn) == LOW)&&(subRes == 0)){ //ВКЛЮЧИТЬ СИРЕНУ И УСТАНОВИТЬ ТЕМПЕРАТУРУ
/*
encBtnCl = subRes;
Serial.println(encBtnCl);
*/
}
if ((digitalRead(encBtn) == LOW)&&(subRes == 1)){ //ВЫКЛЮЧИТЬ НАСОС
/*
encBtnCl = subRes;
Serial.println(encBtnCl);
*/
}
if ((digitalRead(encBtn) == LOW)&&(subRes == 2)){ //ВЫХОД
lcd.clear();
lcd.setCursor(6,0);
lcd.print("MENU");
lcd.setCursor(0,1);
lcd.print(indexMenu[result]);
encBtnCl = 3;
menu();
}
}
///////////////////////////////////////////////////////
encBtnCl = 0;
subRes = -1;
}
}///////////////////////////////////////////----КОНЕЦ ПУНКТА ПОДМЕНЮ 3
/////////////////////////////////////////////////----ВЫХОД ИЗ МЕНЮ----////////////////////////
if ((digitalRead(encBtn) == LOW)&&(result == 3)) {
Serial.println("exit");
setMenuCl = 1;
}
}
/////////////////////////////----КОНЕЦ МЕНЮ----///////////////////////////////////////////////////////////////////////////
Решил и я использовать энкодер, купил простой, похожий на KY-040, почитал, посмотрел. Залил стандартный код под него, которого на просторах много, покрутил. Срабатывало с ошибками, крутишь 3 раза в одну, а он 2 в одну, 1 обратно... Решил посмотреть на дребезг... "шумность" за гранью ))
код, и результат поворота на одно деление по обоим выводам:
volatile int x = 0;
volatile int y = 0;
int a = 0;
int b = 0;
void setup()
{
attachInterrupt(0, encoderX, FALLING); //clk
attachInterrupt(1, encoderY, FALLING); //dt
Serial.begin(57600);
}
void loop()
{
if(x!=a)
{
Serial.print("X - ");
Serial.println(x);
a=0;
x=0;
}
if(y!=b)
{
Serial.print("Y - ");
Serial.println(y);
b=0;
y=0;
}
Serial.println("delay");
delay(5000);
}
void encoderX()
{
x++;
}
void encoderY()
{
y++;
}
left right
X - 8 X - 34
Y - 52 Y - 3
delay delay
X - 12 X - 35
Y - 58 Y - 1
delay delay
X - 20 X - 6
Y - 7 Y - 2
delay delay
X - 2 X - 3
Y - 29 Y - 1
delay delay
X - 5 X - 1
Y - 2 Y - 2
delay delay
X - 4 X - 32
Y - 4 Y - 18
delay delay
X - 18 X - 2
Y - 16 Y - 1
delay delay
X - 2 X - 1
Y - 31 Y - 4
delay delay
X - 60 X - 15
Y - 53 Y - 3
delay delay
X - 13 X - 36
Y - 13 Y - 3
delay delay
X - 10 X - 59
Y - 16 Y - 3
Прицепил конденсаторы на землю по 1мкФ, стало чуть лучше, но не принципиально. Вменяемого результата удалось получить при емкости конденсаторов в 4мкФ, но полностью от дребезга всё равно не удалось избавиться. Недостатком большой емкости стало "медленное" срабатывание, т.е. при большой скорости вращения пропускает шаги.
Результат не без погрешности, но явно лучше, чем без конденсаторов. Предполагаю, будет более правильный результат, если подключить энкодер к мк через резисторы небольшого сопротивления, уменьшив емкость, но таких сейчас под рукой нет ((
у меня в мониторе порта тоже пропуски есть(я по самому первому скетчу) менял время для дребезга- сильно не помогло. или макетка постоянного контакта не поддерживает(хотя энклндер вывел на провода) или энкондер подыхает- со стиральной машинки снял
Начал делать проект паяльной станции (фен+паяльник) и уперся в, казалось бы , элементарную проблему. Ни библиотечная версия, ни куча реализаций работы энкодера на этом форуме меня не устраивают - пропуски шагов, несрабатывание. И энкодер новый, и выводы подтянуты 10кОм резисторами и заблокированы 10нФ кондерами, а не работает энкодер нормально. Единственная реализация которая работала - это реализация в посте #74 - вот такая реализация работает без сбоев и проскакиваний. Но практическое применение такой реализации не имеет смысла - так просто поиграться с энкодером, не более, а иначе все процессорное время будет занято обработкой энкодера. Все реализации через прерывания - это для идеального энкодера. Вы все хорошие программисты, но не практики. Да, должно быть так, но в реале - совсем не так. При вращении энкодера на увеличение, возможны не только несрабатывания (а их может быть 50%), но возможны даже шаги на уменьшение, ну и наоборот! Так, что рано почивать на лаврах, тема не закрыта. Через недельку продолжу свои мучения и отпишусь о своих опытах.
Начал делать проект паяльной станции (фен+паяльник) и уперся в, казалось бы , элементарную проблему. Ни библиотечная версия, ни куча реализаций работы энкодера на этом форуме меня не устраивают - пропуски шагов, несрабатывание. И энкодер новый, и выводы подтянуты 10кОм резисторами и заблокированы 10нФ кондерами, а не работает энкодер нормально. Единственная реализация которая работала - это реализация в посте #74 - вот такая реализация работает без сбоев и проскакиваний. Но практическое применение такой реализации не имеет смысла - так просто поиграться с энкодером, не более, а иначе все процессорное время будет занято обработкой энкодера. Все реализации через прерывания - это для идеального энкодера. Вы все хорошие программисты, но не практики. Да, должно быть так, но в реале - совсем не так. При вращении энкодера на увеличение, возможны не только несрабатывания (а их может быть 50%), но возможны даже шаги на уменьшение, ну и наоборот! Так, что рано почивать на лаврах, тема не закрыта. Через недельку продолжу свои мучения и отпишусь о своих опытах.
Все реализации через прерывания - это для идеального энкодера. Вы все хорошие программисты, но не практики. Да, должно быть так, но в реале - совсем не так. При вращении энкодера на увеличение, возможны не только несрабатывания (а их может быть 50%), но возможны даже шаги на уменьшение, ну и наоборот! пытах.
Это нормально, не думайте, что те кто писал свои обработчики мало в этом понимают. Есть один нюанс -все энкодеры разные. Есть три основных вида, которые в свою очередь образуют ещё подвиды. И все они между собой плохо совместимы. У меня есть два типа, и могу о них рассказать. Первый популярный ky-40
При одном щелчке он даёт вот такую осциллограмму :
Видно, что контакты совершают только одно переключение. Была единица -стал ноль, и на этом устаканилось. При следующем щелчке из ноля перейдёт в единицу, и так по кругу. Теперь берём другой энкодер. Вот такой, продавался под названием модели ec-11
При тех же самых настройках осциллографа делаю с такой же скоростью один щелчок.
Опа, а тут за один щёлчок полный импульс. Есть третий тип энкодеров - делает сразу два таких -же полных импульса. Правда сам таких не видел, но люди писали что они есть. А теперь пару слов о подвидах. Обратите внимание на вторую осциллограмму. Синий импульс существенно длиннее жёлтого, и заканчиваются они почти одновременно. Есть другой вариант этого типа - где оба контакта производят импульсы одинаковой длины. И разница в сдвиге "фаз" у всех тоже разная. Т.е. все энкодеры работают в индивидуальных временных стандартах, и сделать универсальный обработчик довольно сложно. Есть ещё дополнительные факторы, влияние которых может нарушить работу обработчика. В случае обработчика в loop -это сильный отбор процессорного времени на каких-то функциях. В случае обработчика на прерываниях -это неверная разводка земли, прочие помехи, которые вызывают самопроизвольное срабатывание прерываний. Создаётся полная иллюзия, что глючит обработчик -счёт может пропускаться, идти в другую сторону, но на самом деле это просто ложные срабатывания прерываний. Дребез контактов тоже у всех разный, у некоторых энкодеров его почти нет, некоторые будучи ещё новыми уже дребезжат как десятилетние. Всё это нужно учитывать индивидуально.
Элементарно. Грязь и окисление контактов. Ну и "пропил" конечно же. Разобрать, зачистить и будет "как новый". или правильный кондер, точнее "НЧ фильтр". :)
Элементарно. Грязь и окисление контактов. Ну и "пропил" конечно же. Разобрать, зачистить и будет "как новый". или правильный кондер, точнее "НЧ фильтр". :)
отсюда вывод: на скоростные балалайки ставим оптические энкодеры, на медленные - механику.
*интересно, нарыть полный даташит на механический энкодер и прочитать рекомендуемую производителем максимальную скорость вращения вала энкодера, рекомендуемую схему подключения, что бы прекратить заниматься извращениями.
**рекомендацию тестировать код на убитом энкодере считаю странной.
интересно, нарыть полный даташит на механический энкодер
Какое странное желание, еще понять дворец или принца на белом коне. Ну ладно. Трахтибидох -http://www.platan.ru/pdf/datasheets/bourns/pec12.pdf
Какое странное желание, еще понять дворец или принца на белом коне. Ну ладно. Трахтибидох -http://www.platan.ru/pdf/datasheets/bourns/pec12.pdf
я хотел полный даташит - в предложенном не увидел максимальную скорость вращения вала, пока он не начнёт гореть и рекомендуемую схему подключения.
Я вообще слабо понимаю проблему. Вроде как не гипермассовое производство (для себя любимого, ну на крайняк ещё для 10-100 таких же, кто купит и то "может быть"), чтобы экономить на оптическом энкодере, который либо собирается из 2-х деталек по 3 коп. за ведро, или они же выдираются из старых мышек, коих "завались" на любом офисе. Подойди к любому эникейщику, он тебе этих сдохших мышей прямо в ведро и отсыплет. Себе так наковырял рабочих переключательных кнопок штук 30 для "датчиков касания" (в Лего исполнении продаются по .. 1500руб/шт!) и пар светодиод-транзистор с дырчатыми колесиками .. нафига вообще в наше время нужны эти "скользящие трещётки"?
В самом верху: max speed 100rpm Для числовых параметров нормирована 15rpm. Стоит в скобках.
Кстати, писал уже про китайские 130-е моторы с оптическими энкодерами на валу .. Ардуино мега вполне справляется с подсчетом скорости вращения 8000rpm по прерываниям (фронт/срез) как миниум 2-х моторов одновременно. Покупал по $1/шт .. вместе с мотором вот, в конце сентября 2015 и пришли.
В самом верху: max speed 100rpm Для числовых параметров нормирована 15rpm. Стоит в скобках.
да - при более внимательном просмотре увидел, что врщать нужно не чаще одного оборота за 0,6 секунды
нафига вообще в наше время нужны эти "скользящие трещётки"?
схожу закрою завод - пусть владельцы китайских автомагнитол сгорят в аду.
В предыдущем посте слово "владельцы" необходимо читать как "производители".
В предыдущем посте слово "владельцы" необходимо читать как "производители".
производителю пофиг, где будут гореть владельцы их автомагнитол.
Мой вариант обработчика энкодера. Очень простой и совершенно безглючен. Обработчик сидит в теле внешнего прерывания PCINT. В нижеследующем скетче задействованы входы A0 и A1 как цифровые. Используется подтяжка к питанию (распаянная на платке стандартного энкодера), и антидребезговые конденсаторы 0,1мкф на землю. Кому нужно на другие ноги - смотреть даташит страница 73 и маскировку битов сделать по аналогии.
dimax Если не затруднит, расскажите пожалуйста по коду. Только начал осваивать arduino очень многое непонятно. С этим кодом мой энкодер прекрасно работает только в сторону увеличения, в сторону уменьшения никак не хочет. Подскажите пожалуйста в чем может быть проблема. И еще один маленький вопрос, как ограничить максимальное значение переменной enc например до 50 и минимальное до 0. Извините за глупые вопросы, только учусь.
ii_alex, я потом ещё упростил обработчик энкодера, вот последний вариант (для входов A0 и A1):
По коду что сказать? Тут всё базируется на прерывании PCINT и двоичной математике. Читается порт, если его младшие биты в сумме своих весов дают те значения, что указаны в скетче то делается вывод, что энкодер крутили в ту или другую сторону. Для этого способа обязательно нужны конденсаторы на землю от обоих выводов энкодера. Ёмкость зависит от конкретного энкодера, 0,1мкф у меня нужно было на очень старом, убитом энкодере. На новом достаточно будет 0,001мкф. Если в одну сторону инкременируется, а в другую нет, то скорее всего недостаточная ёмкость конденсатора. Или его вообще нет :) И подтяжка к питанию на плате энкодера конечно должна быть.
Версия с ограничением от 0 до 50. В первой строке начальное значение.
dimax Спасибо за ответ ! Пытаюсь вникать. Энкодер обычный, резики подтяжки распаяны, конденсаторы стоят на 0,1 мкф. Если залить ваш скетч из соседней ветки, где обсуждается (отличная вешь, генератор). То энкодер работает без проблем, в любую сторону. Значит подключение A0 A1, емкости, резисторы, все в порядке. А с эти скетчем нивкакую в сторону уменьшения. Последний, который самый упрощенный, к сожалению смогу попробовать только завтра. А так хочется !
ii_alex, последний -это и есть тот, который из "генератора.." :) Но первый вариант тоже рабочий на 100%, не знаю в чём может быть дело у вас.
ii_alex, последний -это и есть тот, который из "генератора.." :) Но первый вариант тоже рабочий на 100%, не знаю в чём может быть дело у вас.
dimax в скетче генератора немного по другому:
Значит подключено к другим выводам (скорее всего к PC1 и PC2). А в варианте выше - PC0 и PC1.
Только вот совершенно не понятно, зачем ещё условие n==1. Ибо оно может только навредить, т.к. будет читаться ещё и значение с соседнего вывода (PC0).
Кстати, если в обработчик добавить обработку времени, например на пару ms, то кондёры из схемы можно смело выкидывать.
ISR (PCINT1_vect){
Как верно подметил Alexino так работать вообще не должно. Обратите внимание, при считанной единице с порта получается и enc+ и enc -, а это абсурд. Если у вас работает, значит читаются только 4 или 6, и скорее всего значения меняются не каждый раз, а через один щелчок. В оригинале было 4-2 6-0.
Кстати, если в обработчик добавить обработку времени, например на пару ms, то кондёры из схемы можно смело выкидывать.
Хоть это и нарушение идеологии прерываний, но как нибудь проверю такой вариант из спортивного интереса:)
Хоть это и нарушение идеологии прерываний, но как нибудь проверю такой вариант из спортивного интереса:)
Существует системный таймер, который можно читать с помощью millis(). Думаю, об этом Вы в курсе. Ну а дальше дело техники )
Причём, я не зря назвал цифру 2, т.к. при использовании системного таймера, разница в 1 мс = 0...1 мс, и можно нарваться на самое минимально время, при котором дребезг будет учтён.
А при отслеживании разницы в 2 мс., мы гарантированно отсеиваем целую миллисекунду. А диапазон времён будет = 1...2 мс.
dimax в оригинале действительно 4-2 6-0. Только в этом варианте получается, что энкодер срабатывает через 2 значения т.е было 1 вращаем становится 3. Чтобы получить 2 нужно вращать энкодер очень очень медленно и буквально чуть-чуть тогда сработка на 1 если крутить стандартно то обрабатывается 2 значения. Я только учусь по этому экспериментировал. Тот код который выложил работает отлично, все считается по 1 в любую сторону, но код неправильный. Подскажите пожалуйста как правильно обработать.
ii_alex, значит у вас энкодер другого типа. На один физический щелчок он дёргает прерывание 2 раза. В теме про генератор обсуждался такой вариант, почитайте сообщение #52 Можно как вариант убрать одну цифру. if ( n==4) {enc++;} if (n==6) {enc--;}
А мааааааааленькую фотографию энкодэра можно посмотреть?
Или название какое у него имеется?
Может просто с кондёрами переборщили? 1-10 нан - я бы больше не ставил.
ii_alex, Я имел ввиду, что нужно сделать либо как в #52, либо убрать одну цифру. А вы взяли как в 52 + убрали цифру. Но раз второй вариант заработал , то и ладно.
До боли похож на "обычный" и обсосанный 100 раз.
Должен работать!
http://www.decada.org.ru/project/lessons/bascom_avr/18/
Посмотрите по "полосатым полоскам".
При смене состояния вверх или вниз любого входа ( а это PinChangeInterrupt)
и при 100%, а это главное, отсутствии дребезга ( как раз лечится кондёрчиками, а гистерезис входов нам в этом помогает)
два входа имеют 4 состояния ( потому-что это 2 бита).
И эти состояния будут, как писал dimax: 1,2 или 0,3
if (n==1||n==2) {enc++;}
if (n==3||n==0) {enc--;}
Кстати по поводу кондёрчиков очень важное замечание.
Они заряжаются довольно медленно через резистор привязки,
а вот разряжаются очень быстро через металлический контакт.
Я бы при 20 кОм привязки поставил Ом 510-1000 последовательно на контакты- хоть немного затянуть их разряд.
Досталась панель от неисправной магнитолы, хочу переделать ее для управления чем нибудь другим. Возникла проблема, в ней стоит 3х фазный энкодер вот такой http://www.alps.com/prod/info/E/HTML/Encoder/Ring/EC35AH/EC35AH240403.html Подскажите как его победить, логика работы другая. Пробовал платой нано каждые 10мс опрашивать порты и слать в сериал порт - все видит, но при быстрой прокрутке не успевает. Покупать другую плату где есть больше ног для прерываний? или можно как то по другому?
Опрашивайте чаще.
Реагируйте на смену уровня
Шлите на 115200.....
Приветсвую всех форумчан!!!!
Решил я значит смастерить термомстат на котел в загородном доме.
котел греется дровами и электричесвом
функцианал таков:
при достижении заданой температуры включается насос
обычный термостат для нагревателей
сирена, на случай превышения заданой температуры (на случай, когда увлекся с дровами)
Аппаратная часть
ардуино уно
I2C LCD16x2
енкодер с кнопкой (общий - земля)
кнопка
суть проблемы в написании меню установок... вроде что-то написал, но работает как-то корявенько
прошу помощи! ткните что не так! может как-то оптимизировать....
вот код
Здрасьте, люди добрые!
Прошу поправить скетч. Хочу, чтоб считал с шагом 5, но что-то не выходит.
И, если не затруднит, чтобы не выходило из диапазона [0...255]
new_pos = (Enc_1.read()/4)*5;
new_pos*4
new_pos = (Enc_1.read()/4)*5;
new_pos*4
Безконечный цикл.
Безконечный цикл.
какой цикл? - я тебе показал куски твоего кода, где тебе нужно исправить.
Чет я не врубаюсь про исправления
Чет я не врубаюсь про исправления
заходи через месяц - врубишся
Очень смешно.
Что так трудно указать, как правильно?
Если нет желания помочь, зачем вообще писать что-то.
Решил и я использовать энкодер, купил простой, похожий на KY-040, почитал, посмотрел. Залил стандартный код под него, которого на просторах много, покрутил. Срабатывало с ошибками, крутишь 3 раза в одну, а он 2 в одну, 1 обратно... Решил посмотреть на дребезг... "шумность" за гранью ))
код, и результат поворота на одно деление по обоим выводам:
Прицепил конденсаторы на землю по 1мкФ, стало чуть лучше, но не принципиально. Вменяемого результата удалось получить при емкости конденсаторов в 4мкФ, но полностью от дребезга всё равно не удалось избавиться. Недостатком большой емкости стало "медленное" срабатывание, т.е. при большой скорости вращения пропускает шаги.
итоговый код:
Результат не без погрешности, но явно лучше, чем без конденсаторов. Предполагаю, будет более правильный результат, если подключить энкодер к мк через резисторы небольшого сопротивления, уменьшив емкость, но таких сейчас под рукой нет ((
у меня в мониторе порта тоже пропуски есть(я по самому первому скетчу) менял время для дребезга- сильно не помогло. или макетка постоянного контакта не поддерживает(хотя энклндер вывел на провода) или энкондер подыхает- со стиральной машинки снял
Этот код отлично отрабатывает мой энкодер, но я не могу его правильно совместить в моем "меню".
Пожалуйста помогите!
у тебя скобки открыты н в том месте и закрыты
у тебя скобки открыты н в том месте и закрыты
В каком именно ?
35,,43,44,
ты не правильно скетч вставил, мало кто подскажет
как и я ошибся в строках
35,,43,44,
Там все правильно смотрите внимательно, а лутше загрузите мой скетч и скомпилируйте!
Начал делать проект паяльной станции (фен+паяльник) и уперся в, казалось бы , элементарную проблему. Ни библиотечная версия, ни куча реализаций работы энкодера на этом форуме меня не устраивают - пропуски шагов, несрабатывание. И энкодер новый, и выводы подтянуты 10кОм резисторами и заблокированы 10нФ кондерами, а не работает энкодер нормально. Единственная реализация которая работала - это реализация в посте #74 - вот такая реализация работает без сбоев и проскакиваний. Но практическое применение такой реализации не имеет смысла - так просто поиграться с энкодером, не более, а иначе все процессорное время будет занято обработкой энкодера. Все реализации через прерывания - это для идеального энкодера. Вы все хорошие программисты, но не практики. Да, должно быть так, но в реале - совсем не так. При вращении энкодера на увеличение, возможны не только несрабатывания (а их может быть 50%), но возможны даже шаги на уменьшение, ну и наоборот! Так, что рано почивать на лаврах, тема не закрыта. Через недельку продолжу свои мучения и отпишусь о своих опытах.
Начал делать проект паяльной станции (фен+паяльник) и уперся в, казалось бы , элементарную проблему. Ни библиотечная версия, ни куча реализаций работы энкодера на этом форуме меня не устраивают - пропуски шагов, несрабатывание. И энкодер новый, и выводы подтянуты 10кОм резисторами и заблокированы 10нФ кондерами, а не работает энкодер нормально. Единственная реализация которая работала - это реализация в посте #74 - вот такая реализация работает без сбоев и проскакиваний. Но практическое применение такой реализации не имеет смысла - так просто поиграться с энкодером, не более, а иначе все процессорное время будет занято обработкой энкодера. Все реализации через прерывания - это для идеального энкодера. Вы все хорошие программисты, но не практики. Да, должно быть так, но в реале - совсем не так. При вращении энкодера на увеличение, возможны не только несрабатывания (а их может быть 50%), но возможны даже шаги на уменьшение, ну и наоборот! Так, что рано почивать на лаврах, тема не закрыта. Через недельку продолжу свои мучения и отпишусь о своих опытах.
https://www.youtube.com/watch?v=ejbCYs-WJaY
Все реализации через прерывания - это для идеального энкодера. Вы все хорошие программисты, но не практики. Да, должно быть так, но в реале - совсем не так. При вращении энкодера на увеличение, возможны не только несрабатывания (а их может быть 50%), но возможны даже шаги на уменьшение, ну и наоборот! пытах.
Это нормально, не думайте, что те кто писал свои обработчики мало в этом понимают. Есть один нюанс -все энкодеры разные. Есть три основных вида, которые в свою очередь образуют ещё подвиды. И все они между собой плохо совместимы. У меня есть два типа, и могу о них рассказать. Первый популярный ky-40
При одном щелчке он даёт вот такую осциллограмму :
Видно, что контакты совершают только одно переключение. Была единица -стал ноль, и на этом устаканилось. При следующем щелчке из ноля перейдёт в единицу, и так по кругу. Теперь берём другой энкодер. Вот такой, продавался под названием модели ec-11
При тех же самых настройках осциллографа делаю с такой же скоростью один щелчок.
Опа, а тут за один щёлчок полный импульс. Есть третий тип энкодеров - делает сразу два таких -же полных импульса. Правда сам таких не видел, но люди писали что они есть. А теперь пару слов о подвидах. Обратите внимание на вторую осциллограмму. Синий импульс существенно длиннее жёлтого, и заканчиваются они почти одновременно. Есть другой вариант этого типа - где оба контакта производят импульсы одинаковой длины. И разница в сдвиге "фаз" у всех тоже разная. Т.е. все энкодеры работают в индивидуальных временных стандартах, и сделать универсальный обработчик довольно сложно. Есть ещё дополнительные факторы, влияние которых может нарушить работу обработчика. В случае обработчика в loop -это сильный отбор процессорного времени на каких-то функциях. В случае обработчика на прерываниях -это неверная разводка земли, прочие помехи, которые вызывают самопроизвольное срабатывание прерываний. Создаётся полная иллюзия, что глючит обработчик -счёт может пропускаться, идти в другую сторону, но на самом деле это просто ложные срабатывания прерываний. Дребез контактов тоже у всех разный, у некоторых энкодеров его почти нет, некоторые будучи ещё новыми уже дребезжат как десятилетние. Всё это нужно учитывать индивидуально.
Дополню: есть различные схемы подключения энкодеров. Я могу порекомендовать такую:
Дополню: есть различные схемы подключения энкодеров. Я могу порекомендовать такую:
конденсаторы, что бы прерывание аппаратно затупить? :D
Кстати, насчет конденсаторов: схему естественно, подключать только к тем ногам МК, у которых есть триггера Шмитта.