… так сразу и танцуй )))
Смотрю дискуссия пошла по новому кругу))
Ещё одна мысль пришла. Может покажется смешной.
Я ESP32 не юзаю, лишь по верхам. Понял, что много чего знать надо.
Возможно, дело во времени обработки прерывания.
Может ли RTOS как то это замедлить?
В таком случае, логично, что уровень на пине успеет измениться.
Если есть уно/нано мой совет, проверьте на них.
Стащил у сына Uno. Загрузил код из #41 (с необходимыми правками)
Там почти всегда 0 (т.е. ожидаемое поведение). Иногда проскакивает 1, но это я вполне могу объяснить дребезгом. Тем более что она проскакивает и “влево” и “вправо”, что тоже логично.
Значит, в итоге разбираться нужно с esp, а не с энкодером. Но там факторов, которые могут повлиять много (включая конкретный экземпляр esp), это не энкодер с двумя контактами. В рамках форума, пожалуй, будет сложновато.
Если кто-то знает, какой конкретно фактор в данном случае влияет, буду благодарен.
@MMM , не подскажете, на чем проверяли?
Классик Нано
ТС, посмотри уже пример в этой библиотеке и сделай так же:
Здесь есть спецы по ESP32, может ответят.
Моя версия дилетанта - эти ардуино- прерывания, не совсем прерывания , они обрабатываются операционкой.
Как напрямую к железу обратиться не знаю, да и надо ли.
Ведь можно и без прерываний решить эту задачу.
А выше ещё писали про встроенный модуль энкодера…
Дельная мысль.
Я тоже не спец по ЕСП32, но “где-то слышал”, что для использования хардварных прерываний ЕСП32 обработчик должен начинаться с ключевого слова IRAM_ATTR:
// Обработчик прерывания по нажатию кнопки
static void IRAM_ATTR isrButtonPress(void* arg)
{
// Что-то делаем..
}
А у ТС в коде этого нет:
Звучит как заклинание. ))
спасибо , переделал стенд , и на нем сейчас все проверю
у меня есть многое что нужно для разработки домашнего хобита.
могу многое . CAM ,. инженерия . владения всеми инструментами. . ну и конечно 3 д принтером не проффесианально но все же . нет осцилогрофа .
не умею паять хотя все есть . не умею писать код. но что то из кусков собрать и поправить под свои задачи могу .
можете по необходимости спросить я постараюсь проверить ваши хотелки .
Это заклинание переносит процедуру в оперативную память. В противном случае она будет исполняться так же, как и всё остальное - подгружаясь со SPI EEPROM со всеми вытекающими накладными расходами.
проверил ,. вроде стабильно , дребезга с виду нет , шим растянутый но вроде чистый на скорости 1000 мм мин.
что бы я смог его проверить на качество шима мне нужно его привести что бы он выдавал либо 1,0,1. или 1,1,-1-1 кто может подправте код. сам я наверное смогу но буду долго эксперементировать. ,
и я проверю сразу на шаговике , там четко дребезг если он есть проявится
шаговик в код я подброшу , тоже надеюсь
и чуть позже могу выложить видио или организовать трансляцию. что бы попробывать ваши вопросы по энкодеру
простой энкодер тоже есть
код посмотрел , может я так шаговик подкину. , сейчас поэкспериментирую .
если кто быстрей сдедает киньте код
у меня такие выводы и плиз без библиотеки
volatile int enc;
#define STEP_PIN 2
#define DIR_PIN 5
#define ENABLE_PIN 8
void setup() {
Serial.begin(230400);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
PCIFR=PCIFR; PCICR=1<<PCIE1; //разрешить прерывание
PCMSK1=1<<PCINT8 | 1<<PCINT9; //выбрать вход на котором сработает прерывание
pinMode(2, OUTPUT);
pinMode(5, OUTPUT);
pinMode(8, OUTPUT);
}
так шаговик я накинул но крутит в одну сторону либо в левую либо в правую .
ищем почему .
помогайте я тоже внимательно поизучаю
//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
volatile int enc, motor_position;
#define STEP_PIN 2
#define DIR_PIN 5
#define ENABLE_PIN 8
void setup(){
Serial.begin(9600);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
PCIFR=PCIFR; PCICR=1<<PCIE1; //разрешить прерывание
PCMSK1=1<<PCINT8 | 1<<PCINT9; //выбрать вход на котором сработает прерывание
pinMode(2, OUTPUT);
pinMode(5, OUTPUT);
pinMode(8, OUTPUT);
}
ISR(PCINT1_vect){
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
if(!(PINC & (1 << PC0))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(EncCur != EncPrev) //если состояние изменилось,
{
if(EncPrev == 3 && //если предыдущее состояние 3
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if(EncCur == 2)
enc++;
digitalWrite(DIR_PIN , LOW);
digitalWrite(ENABLE_PIN , LOW);
digitalWrite(STEP_PIN , HIGH);
if(EncPrev%2) {
digitalWrite(STEP_PIN , LOW);
++motor_position;
}
}
else
enc--;
digitalWrite(DIR_PIN ,HIGH );
digitalWrite(ENABLE_PIN , LOW);
digitalWrite(STEP_PIN , HIGH);
if(EncPrev%2) {
digitalWrite(STEP_PIN , LOW);
++motor_position;
}
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur; //сохранение предыдущего состояния
}
}
void loop() {
Serial.println(enc);
}
есть проблема , этот код считывает только в минус -1,-120
пины на энкодере менял и по одному пину ставил все идет в минус
этот код нужно исправлять .
этого не может быть
блин , не может это я что то понаписал
буду перепроверять
спасибо а то я уже дальше переписывать начал
у тебя концептуальная ошибка:
- должен быть датчик нулевого положения каретки
- в струйных принтерах не просто так установлен оптический датчик и линейка
- если нужна точность, а у тебя вижу в схеме индикатор, смотри как сделано в струйном принтере
А твк?
Спойлер
ISR(PCINT1_vect)
{
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
if(!(PINC & (1 << PC0))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(EncCur != EncPrev) //если состояние изменилось,
{
if ((EncPrev == 0 && EncCur == 1) || (EncPrev == 3 && EncCur == 2))
{
enc++;
digitalWrite(DIR_PIN , LOW);
digitalWrite(ENABLE_PIN , LOW);
digitalWrite(STEP_PIN , HIGH);
if(EncPrev%2) {
digitalWrite(STEP_PIN , LOW);
++motor_position;
}
}
if ((EncPrev == 1 && EncCur == 0) || (EncPrev == 2 && EncCur == 3))
{
enc--;
digitalWrite(DIR_PIN ,HIGH );
digitalWrite(ENABLE_PIN , LOW);
digitalWrite(STEP_PIN , HIGH);
if(EncPrev%2) {
digitalWrite(STEP_PIN , LOW);
++motor_position;
}
}
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur;
} //сохранение предыдущего состояния
}
все , раскидал
теперь двигатель крутится куда и энкодер
сейчас погоняем на всех скоростях. и посмотрим шим
я пока с делей сделал погоняю переделаю немного по другому
такмка будет точнее показывать
//Энкодер на пинах А0, А1. Используется внутренняя подтяжка.
volatile int enc, motor_position;
#define STEP_PIN 2
#define DIR_PIN 5
#define ENABLE_PIN 8
void setup(){
Serial.begin(9600);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
PCIFR=PCIFR; PCICR=1<<PCIE1; //разрешить прерывание
PCMSK1=1<<PCINT8 | 1<<PCINT9; //выбрать вход на котором сработает прерывание
pinMode(2, OUTPUT);
pinMode(5, OUTPUT);
pinMode(8, OUTPUT);
}
ISR(PCINT1_vect){
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
if(!(PINC & (1 << PC0))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PINC & (1 << PC1))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(EncCur != EncPrev) //если состояние изменилось,
{
if(EncPrev == 3 && //если предыдущее состояние 3
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if (EncCur == 2) //если текущее состояние 2,
(enc++, digitalWrite(DIR_PIN , 1), Step());
else //иначе
(enc--, digitalWrite(DIR_PIN , 0), Step());
}
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur; //сохранение предыдущего состояния
}
}
void Step() {
digitalWrite(ENABLE_PIN , LOW);
digitalWrite(STEP_PIN , HIGH);
delay(1);
digitalWrite(STEP_PIN , LOW);
++motor_position;
}
void loop() {
Serial.println(enc);
}


