zepete: (Default)
[personal profile] zepete

К аналоговому входу arduino можно приделать потенциометр вместо галетного выключателя для выбора опций нескольких опций, но считанное значение будет дрожать.

Для предотвращения этого я использую 4 метода:

  • считываю значение за несколько раз;
  • игнорирю изменение значения на 1;
  • игнорирую младший разряд;
  • добавляю 3 резистора, одним концом подключенным к цифровым входам/выходам arduino, а другим к аналоговому входу с потенциометром, для обеспечения притягивания выходного напряжения внутрь диапазона текущей опции за счет правильно разработанного управления ими.

image

Для другого потенциометра надо будет использовать другие резисторы. Я весь диапазон значений АЦП поделил на три части: две краевые зоны и одну внутреннюю, ибо если использовать только одну зону с одним резистором номиналом в 330К, то на краях он влиять на уровень напряжения не будет, хотя в середине будет давать отклонение на 2 (10мВ), а на краях до меньше половины разряда (5мВ при входном значении равном 83). Причем величина влияния будет падать очень быстро до нуля. В моем решении, величина гистирезиса всегда больше половины разряда, но меньше двух разрядов. Фрагмент исходного кода для реализации этого

#define   MIDDLE_ADC  41      // края ADC,
.......
.......
const   int      ciRes330k=5;
const   int      ciRes33k=4;
const   int      ciRes560=13;
const   int      ciOptionPin=0;
........
........
int     iNumOption=10; // сколько возможно опций
int     iNewSUM=1024;
.......
.......
void loop() {
  // чтение номера канала с усреднением
  static  word  wNumRead=0;
  static  unsigned long sum;
  static  unsigned long iADC=2048;
  static  unsigned int iNewOption=2048;
  if(!wNumRead)
    sum=0;
  sum+=analogRead(ciOptionPin);
  wNumRead+=1;
  if(wNumRead==AVR)
  {
    // номер канала считан
    wNumRead=0;
    sum=sum/AVR;
    // удаление помехи
    if(abs(iADC-sum)==1)
      sum=iADC;
    else
      iADC=sum;
    sum=sum/2;
    if(iNewSUM!=sum)
    {
      // установка подтягивающих резистров для обеспечения не большой положительной связи
      // требуется для устранения помех
      if((2*sum-(int)(sum*(long)512/(long)iNumOption)-(int)((sum+1)*(long)512/(long)(iNumOption))+1)>0)
      {
        // ближе к верхней границе диапазона, значит надо притягивать к минусу
        // проверка на размер уровня 
        if(sum<MIDDLE_ADC)
        {
          // нижний диапазон
          pinMode(ciRes330k,INPUT);
          pinMode(ciRes33k,INPUT); 
          pinMode(ciRes560,OUTPUT);
          digitalWrite(ciRes560,LOW);
        }
        else
        {
          if(sum<511-MIDDLE_ADC)
          {
            // средний диапазон
            pinMode(ciRes330k,OUTPUT);
            pinMode(ciRes33k,INPUT); 
            pinMode(ciRes560,INPUT);
            digitalWrite(ciRes330k,LOW);
          }
          else
          {
            pinMode(ciRes330k,OUTPUT);
            pinMode(ciRes33k,INPUT); 
            pinMode(ciRes560,INPUT);
            digitalWrite(ciRes33k,LOW);
          }
        }
      }
      else
      {
        // ближе к нижней границе диапазона, значит надо притягивать к плюсу
        if(sum<MIDDLE_ADC)
        {
          // нижний диапазон
          pinMode(ciRes330k,INPUT);
          pinMode(ciRes33k,OUTPUT); 
          pinMode(ciRes560,INPUT);
          digitalWrite(ciRes33k,HIGH);
        }
        else
        {
          if(sum<511-MIDDLE_ADC)
          {
            // средний диапазон
            pinMode(ciRes330k,OUTPUT);
            pinMode(ciRes33k,INPUT); 
            pinMode(ciRes560,INPUT);
            digitalWrite(ciRes330k,HIGH);
          }
          else
          {
            pinMode(ciRes330k,INPUT);
            pinMode(ciRes33k,INPUT); 
            pinMode(ciRes560,OUTPUT);
            digitalWrite(ciRes560,HIGH);
          }
        }
      }      
      iNewSUM=sum;
 ......
 ......
}


Date: 2014-02-20 05:26 pm (UTC)
From: [identity profile] xorkrus.livejournal.com
А у вас случайно нет идеи как ардуину с энкодером, заюзать вместо резистора переменного?

Date: 2014-02-20 06:47 pm (UTC)
From: [identity profile] zepete.livejournal.com
Там с одной стороны проще (нет необходимости аналоговые помехи подавлять), а с другой сложнее (в eeprom надо положение сохранять, которое иногда стирается при медленном выключении питания).

http://www.mirmk.net/content/view/84/29/
http://arduino.cc/en/Main/ArduinoBoardNano#.UwZF7eVhwVQ
http://arduino.cc/en/Reference/AttachInterrupt#.UwZGgOVhwVQ
То есть. один вывод энкодера подключаются к d2 или d3, а другой к любому другому цифровому входу.
Описываются две переменные размером с байт, одна для хранения текущего значения положения, а другая последнего сохраненного.
byte byEncoder, byEncoderOld;
В setup прописывается программа вызова прерывания по фронту спадающему или поднимающемуся и инициализируется переменная положения энкодера.
Например так attachInterrupt(2,EncoderSub,RISING) - для случая подключения к d2.
void setup(void)
{
......
// задание значения энкодера, с простейшей проверкой целостности данных
byEncoder=EEPROM.read(0);
byEncoderOld=EEPROM.read(1);
if(byEncoder!=byEncoderOld)
byEncoder=byEncoderOld=0;
// задание режима входов, если надо подтягивать к плюсу, то вместо INPUT надо писать INPUT_PULLUP
pinMode(2,INPUT);
pinMode(3,INPUT);
attachInterrupt(2,EncoderSub,RISING);
......
}
Пишется подпрограмма обработки прерывания EncoderSub, в которой положение энкодера инкрементируется при положительном значении второй ноги энкодера и декрементируется при отрицательном значении.
Например так.
void EncoderSub(void)
{
if(digitalRead(3))
byEncoder+=1;
else
byEncoder-=1;
}

В программе цикла сравниваются byEncoder и byEncoderOld, если не равны, то переписывается значение в eeprom
void loop(void)
{
....
if(byEncoder!=byEncoderOld)
{
byEncoderOld=byEncoder;
EEPROM.write(0,byEncoder);
EEPROM.write(1,byEncoder);
}
...
}

Приблизительно так.
Возможно еще придется с дребезгом при переключении бороться при помощи таймера.
Edited Date: 2014-02-20 06:48 pm (UTC)

Date: 2014-02-20 07:59 pm (UTC)
From: [identity profile] xorkrus.livejournal.com
За это спасибо тоже, но есть, допуcтим БП. У него на трех проводах висит резистор переменный. Как вместо него подключить ардуино с энкодером.

Date: 2014-02-20 08:11 pm (UTC)
From: [identity profile] zepete.livejournal.com
Простой способ с помехой около 0.1В: ШИП при помощи аппаратного PWM в avr, диода шотки, p-канального полевого транзистора, дросселя и конденсатора.

Сложный способ: добавлять внешний ЦАП, возможено много вариантов от набора резистров на цифровых выходах ардуино с операционным усилителем, до спецмикросхемы.

Profile

zepete: (Default)
zepete

January 2026

S M T W T F S
    1 23
4 56 78910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 14th, 2026 02:08 pm
Powered by Dreamwidth Studios