К аналоговому входу arduino можно приделать потенциометр вместо галетного выключателя для выбора опций нескольких опций, но считанное значение будет дрожать.
Для предотвращения этого я использую 4 метода:
- считываю значение за несколько раз;
- игнорирю изменение значения на 1;
- игнорирую младший разряд;
- добавляю 3 резистора, одним концом подключенным к цифровым входам/выходам arduino, а другим к аналоговому входу с потенциометром, для обеспечения притягивания выходного напряжения внутрь диапазона текущей опции за счет правильно разработанного управления ими.
Для другого потенциометра надо будет использовать другие резисторы. Я весь диапазон значений АЦП поделил на три части: две краевые зоны и одну внутреннюю, ибо если использовать только одну зону с одним резистором номиналом в 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; ...... ...... }

no subject
Date: 2014-02-20 05:26 pm (UTC)no subject
Date: 2014-02-20 06:47 pm (UTC)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);
}
...
}
Приблизительно так.
Возможно еще придется с дребезгом при переключении бороться при помощи таймера.
no subject
Date: 2014-02-20 07:59 pm (UTC)no subject
Date: 2014-02-20 08:11 pm (UTC)Сложный способ: добавлять внешний ЦАП, возможено много вариантов от набора резистров на цифровых выходах ардуино с операционным усилителем, до спецмикросхемы.