Джойстик на цифровых пинах

lilik
Offline
Зарегистрирован: 19.10.2017

Создал отдельную тему из-за непонятного феномена по мотивам емкостного сенсора из соседней темы. Сделал скетч для джойстика:

#define sens_X 4
#define sens_Y 12
#define seria 10
int TIK_X=0;
int TIK_Y=0;

void setup() {
 Serial.begin(9600); 
}
void loop() {
sensor_data();  
delay(200);   
}   
void sensor_data() {
/////////////////////////////////////////////////////////////////////////////////////////////// 
 TIK_X=0;
  for(int i=0;i<seria;i++)// делаем серию замеров
  {
int tik_X = 0;
 pinMode (sens_X, OUTPUT);//
 delay(1);
 pinMode (sens_X, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
  while (!digitalRead(sens_X)) { //пока не будет лог1, считаем tik-и
  tik_X++;
}
TIK_X=TIK_X+tik_X;
  }
 TIK_X=TIK_X/seria;// вычисляем среднее значение в серии
 Serial.print(TIK_X); //пишем усреднённый результат 
 Serial.print("   "); 
 ///////////////////////////////////////////////////////////////////////////////////////////////
  TIK_Y=0;
  for(int i=0;i<seria;i++)// делаем серию замеров
  {
int tik_Y = 0;
 pinMode (sens_Y, OUTPUT);//
 delay(1);
 pinMode (sens_Y, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
  while (!digitalRead(sens_Y)) { //пока не будет лог1, считаем tik-и
  tik_Y++;
}
TIK_Y=TIK_Y+tik_Y;
  }
 TIK_Y=TIK_Y/seria;// вычисляем среднее значение в серии
 Serial.println(TIK_Y); //пишем усреднённый результат 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 }

всё работает, в нейтральном положении в мониторе идут числа около 90. При манипуляциях рычагом значения по осям меняются "+-" от 20 до 160. Решил разделить функцию на две по осям:

#define sens_X 4
#define sens_Y 12
#define seria 10

void setup() {
 Serial.begin(9600);
 }
void loop() {
sensor_X_data(); 
sensor_Y_data();
delay(200);
}   
void sensor_X_data() {
/////////////////////////////////////////////////////////////////////////////////////////////// 
int TIK_X=0;
  for(int i=0;i<seria;i++)// делаем серию замеров
  {
int tik_X = 0;
 pinMode (sens_X, OUTPUT);//
 delay(1);
 pinMode (sens_X, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
  while (!digitalRead(sens_X)) { //пока не будет лог1, считаем tik-и
  tik_X++;
}
TIK_X=TIK_X+tik_X;
  }
 TIK_X=TIK_X/seria;// вычисляем среднее значение в серии
 Serial.print(" "); 
 Serial.println(TIK_X); //пишем усреднённый результат 
 ///////////////////////////////////////////////////////////////////////////////////////////////
  }
 void sensor_Y_data() {
/////////////////////////////////////////////////////////////////////////////////////////////// 
 int TIK_Y=0;
  for(int i=0;i<seria;i++)// делаем серию замеров
  {
int tik_Y = 0;
 pinMode (sens_Y, OUTPUT);//
 delay(1);
 pinMode (sens_Y, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
  while (!digitalRead(sens_Y)) { //пока не будет лог1, считаем tik-и
  tik_Y++;
}
TIK_Y=TIK_Y+tik_Y;
  }
 TIK_Y=TIK_Y/seria;// вычисляем среднее значение в серии
 Serial.print("    "); 
 Serial.println(TIK_Y); //пишем усреднённый результат 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 }

ничего не поменялось. Потом решил в программе читать только один переменный резистор, закомментировав строку sensor_Y_data();...

... и неожиданно нейтраль стала выдавать 127 вместо 90, а амплитуда от 25 до 138, аналогично и на второй оси при исключении чтения второй.

Как такое может быть? Как может влиять на время зарядки одного конденсатора присутствие в программе опроса второго? 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

как показывает моя длительная практика уровень логической единицы в реале вещь весьма непостоянная и колеблется от 1.5-1.6 вольта на 5 вольтовой логике, компаратор решит проблему

lilik
Offline
Зарегистрирован: 19.10.2017

ua6em пишет:

колеблется от 1.5-1.6 вольта на 5 вольтовой логике

Соответствующие колебания получаемых значений также минимальны и не влияют на описываемую странность.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

delay(1); точно хватает для разрядки конденсатора ?

lilik
Offline
Зарегистрирован: 19.10.2017

Komandir пишет:

delay(1); точно хватает для разрядки конденсатора ?

Да, хватает, пробовал 2 и больше. Кажется я понял как надо поменять исходную идею этого метода, сейчас по экспериментирую.

lilik
Offline
Зарегистрирован: 19.10.2017

Для корректной работы  надо использовать замеры времени зарядки конденсатора до пороговых значений напряжения, а не значения прироста счётчика:

//////////////////////////////////////////////////////////////////////////
/*
#define sens 4
void setup() {
 Serial.begin(9600); 
}
void loop() {
sensor_data();  
delay(1000);   
}   
void sensor_data() {
int  tik = 0;
  pinMode (sens, OUTPUT);//
  digitalWrite (sens, LOW); // устанавливаем ВЫХОД и 0 для замера времени разрядки кнопки
  delayMicroseconds(10);
 pinMode (sens, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
  while (!digitalRead(sens)) { //пока не будет лог1, считаем tik-и
  tik++;
}
Serial.println(tik); //пишем результат
  }
  */
////////////////////////////////////////////////////////////////////////
#define sens 4
void setup() {
 Serial.begin(9600); 
}
void loop() {
sensor_data();  
delay(1000);   
}   
void sensor_data() {
int  tik = 0;
 pinMode (sens, OUTPUT);//устанавливаем ВЫХОД и 0 для замера времени разрядки кнопки
 delay(1);
 pinMode (sens, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
 long tik_ = micros();
 while (!digitalRead(sens)) { //пока не будет лог1, считаем tik-и
  tik = micros()-tik_;
}
Serial.println(tik); //пишем результат
  }
////////////////////////////////////////////////////////////////////////

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

моросит чуть более 2%, греть чип не пробовал

lilik
Offline
Зарегистрирован: 19.10.2017

Всё таки проблема программная, мне не понятна её природа - почему значение tik зависит от варианта скетча в таком виде:

17  while (!digitalRead(sens)) { //пока не будет лог1, считаем tik-и
18   tik++;
19 }

  и работает правильно-независимо при таком:

38  while (!digitalRead(sens)) { //пока не будет лог1, считаем tik-и
39   tik = micros()-tik_;
40 }

Вот для джойстика ещё правильный вариант:

#define sens_X 4
#define sens_Y 12
#define seria 10

void setup() {
 Serial.begin(9600); 
}
void loop() {
sensor_data();  
delay(200);   
}   
void sensor_data() {
/////////////////////////////////////////////////////////////////////////////////////////////// 
int TIK_X=0;
int TIK_Y=0;
  for(int i=0;i<seria;i++)// делаем серию замеров
  {
int tik_X = 0;
int tik_Y = 0;
  pinMode (sens_X, OUTPUT);//
  pinMode (sens_Y, OUTPUT);//
  delay(1);
 pinMode (sens_X, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
 pinMode (sens_Y, INPUT); // установливаем ВХОД замеряем время зарядки кнопки
 long tik_Yy =0;
 long tik_Xx = tik_Yy = micros();
 while (!digitalRead(sens_X)&&!digitalRead(sens_Y)) { //пока не будет лог1, считаем tik-и
 tik_X=micros()-tik_Xx; tik_Y=micros()-tik_Yy; 
}
 while (!digitalRead(sens_X)) { //пока не будет лог1, считаем tik-и
 tik_X=micros()-tik_Xx;
}
  while (!digitalRead(sens_Y)) { //пока не будет лог1, считаем tik-и
 tik_Y=micros()-tik_Yy;
}
TIK_X=TIK_X+tik_X;
TIK_Y=TIK_Y+tik_Y;
  }
 TIK_X=TIK_X/seria;// вычисляем среднее значение в серии
 TIK_Y=TIK_Y/seria;// вычисляем среднее значение в серии
 Serial.print(TIK_X); //пишем усреднённый результат 
 Serial.print("   ");
 Serial.println(TIK_Y); //пишем усреднённый результат 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 }