digitalRead == ~PINx&(1<<x) ?

fetus

✩✩✩✩✩✩✩
12 Дек 2020
17
0
Приветствую. Использую код для обработки энкодера представленный здесь.
C++:
// алгоритм с "таблицей", позволяющий увеличить точность энкодера
// в 4 раза, работает максимально чётко даже с плохими энкодерами.
// Для увеличения скорости опроса используйте PCINT и чтение из PINn
#define CLK 3
#define DT 2
long pos = 0;
byte lastState = 0;
const int8_t increment[16] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
void setup() {
  Serial.begin(9600);
}
void loop() {
  byte state = digitalRead(CLK) | (digitalRead(DT) << 1);
  if (state != lastState) {
    pos += increment[state | (lastState << 2)];
    lastState = state;
    Serial.println(pos);
  }
}
C digitalRead все работает (правда " перелистывает " сразу по 4 значения ) 0...4...8...12........
по совету из комментариев пытаюсь читать "0" из PIN на выходе белиберда. Подскажите , что я не так делаю?

C++:
long pos = 0;
int8_t  lastState = 0;
const int8_t increment[16] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
void setup() {
 
  Serial.begin(9600);
   DDRC &=~((1<<PC2)|(1<<PC3));
   PORTC |= (1 << PC2)| (1 << PC3) ;

  PCICR |= (1 << PCIE1);   
  PCMSK1 |= (1 << PCINT10) | (1 << PCINT11); 
}

ISR(PCINT1_vect) {
 // uint8_t state = ~PINC&(1<<PC2) | (~PINC&(1<<PC3) << 1);
 uint8_t  state = digitalRead(A2) | (digitalRead(A3) << 1);
  if (state != lastState) {
    pos += increment[state | (lastState << 2)];
    lastState = state;
     pos=constrain(pos,0,255);
    Serial.println(pos);
    }
}

void loop() {
}
 

fetus

✩✩✩✩✩✩✩
12 Дек 2020
17
0
Проблема в том ,что код с 15й строкой вместо 16й не работает как надо. Увеличивает значение pos не зависимо от направления вращения энкодера, причем в одну сторону увеличивает на 30-40, а в другую 1-4 каждый тик. Может я как то не правильно читаю из PIN?
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
Проблема в том ,что код с 15й строкой вместо 16й не работает как надо.
а с чего вы взяли, что конструкция

~PINC&(1<<PC2)
и
digitalRead(A2)

- это одно и то же?

Выведите результат обоих действий в монитор, лучше в бинарном виде - и убедитесь что они дают разный результат

И вдогонку - вопрос. Нафига вы используете в коде эту запись, если не понимаете ее? Чем вас диджиталРеад не устраивает?
 
Изменено:
  • Лойс +1
Реакции: Nikanor

fetus

✩✩✩✩✩✩✩
12 Дек 2020
17
0
а с чего вы взяли, что конструкция

~PINC&(1<<PC2)
и
digitalRead(A2)

- это одно и то же?

Выведите результат обоих действий в монитор, лучше в бинарном виде - и убедитесь что они дают разный результат

И вдогонку - вопрос. Нафига вы используете в коде эту запись, если не понимаете ее? Чем вас диджиталРеад не устраивает?
Хм. ~PINC&(1<<PC2) на выходе 100(4), ~PINC&(1<<PC3) ...1000(8) :oops:
Мне надо "прикрутить" энкодер к тини13 в атмел студио, диджиталРид я же туда не засуну. Так как памяти мало приходится осваивать регистры. Раннее с ними дела не имел.

Сделал так:
C++:
 uint8_t state = (bool)(~PINC&(1<<PC2)) | ((bool)(~PINC&(1<<PC3)) << 1);
не знаю насколько это корректно , но в ардуине работает, посмотрим как атмел студио.
Теперь надо побороть "перелистывание " кратное 4
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
Хм. ~PINC&(1<<PC2) на выходе 100(4), ~PINC&(1<<PC3) ...1000(8)
вы не сравнили эти данные с digitalRead() с этих же пинов.
Вот прям в одной и той же программе прочитайте подряд регистры - выведите в Сериал, а потом и диджитал Реад так же - и убедитесь. что результат совершенно разный
не знаю насколько это корректно , но в ардуине работает, посмотрим как атмел студио.
с точки зрения синтаксиса корректно, с точки зрения смысла программы такой же бред как раньше.

Я не пойму. если вам приходится использовать эту запись - то почему бы для начала не рахобраться. что она делает? Или так и будете вслепую тыкаться?
 

fetus

✩✩✩✩✩✩✩
12 Дек 2020
17
0
Сравнил ~PINC&(1<<PC2) имеет два состояния либо 0 либо 4. ~PINC&(1<<PC3) 0 и 8.
digitalRead(A2) 0 и 1. Поэтому и привел к bool.
 

fetus

✩✩✩✩✩✩✩
12 Дек 2020
17
0
Та где то вычитал если отслеживать пин который меняет состояние с высокого на низкий , то надо использовать ~PINx&(1<<x) , а если наоборот то PINx&(1<<x). Наверное это имелось ввиду какого то контекста .
 

bort707

★★★★★★✩
21 Сен 2020
3,062
912
Та где то вычитал если отслеживать пин который меняет состояние с высокого на низкий , то надо использовать ~PINx&(1<<x) , а если наоборот то PINx&(1<<x).
Воспользуйтесь обычным здравым смыслом
Если digitalRead() у вас был без инверсии, значит чтобы получить такой же результат - и в работе через регистр инверсии быть не должно
 

fetus

✩✩✩✩✩✩✩
12 Дек 2020
17
0
Подскажите тогда ,как грамотно считать конкретный бит из пина. Пробовал вот так (PINC&(1<<PC2))>>2 , (PINC&(1<<PC3))>>3 код работает . Это правильно или костыль?