Решил собрать счетчик кабеля на энкодере, 28ми сегментном индикаторе и Ардуино Uno.
Энкодер у меня 12ти позиционный. Ниже код:
001 | int dig1, dig2, dig3, dig4=0; |
002 | int keys[10] = { 39, 30, 31, 32, 33, 34, 35, 36, 37, 38 }; |
004 | unsigned long Counter = 0; |
006 | unsigned long currentTime; |
007 | unsigned long loopTime; |
010 | unsigned char encoder_A; |
011 | unsigned char encoder_B; |
012 | unsigned char encoder_A_prev=0; |
017 | pinMode(pin_A, INPUT); |
018 | pinMode(pin_B, INPUT); |
019 | currentTime = millis(); |
020 | loopTime = currentTime; |
038 | digitalWrite(1, HIGH); |
039 | digitalWrite(11, HIGH); |
040 | digitalWrite(10, HIGH); |
041 | digitalWrite(9, HIGH); |
049 | currentTime = millis(); |
050 | if (currentTime >= (loopTime + 5)) |
052 | encoder_A = digitalRead(pin_A); |
053 | encoder_B = digitalRead(pin_B); |
054 | if ((!encoder_A) && (encoder_A_prev)) |
070 | dig1=0; dig2=0; dig3=0; dig4=Counter/100; |
073 | if ((Counter < 10000)&(Counter > 999)) |
075 | dig1=0; dig2=0; dig3=Counter / 1000; dig4=(Counter / 100)%10 ; |
077 | if ((Counter < 100000)&(Counter > 9999)) |
079 | dig1=0; dig2=Counter / 10000; dig3=(Counter / 1000) % 10; dig4=(Counter / 100)%10; |
081 | if ((Counter < 1000000)&(Counter > 99999)) |
083 | dig1=Counter/1000000; dig2=(Counter / 10000) %10; dig3=(Counter / 1000) % 10; dig4=(Counter / 100)%10; |
091 | encoder_A_prev = encoder_A; |
092 | loopTime = currentTime; |
097 | void digLED( int pin, int dig) |
100 | digitalWrite(pin, LOW); |
104 | digitalWrite(8, HIGH); |
105 | digitalWrite(7, HIGH); |
106 | digitalWrite(6, HIGH); |
107 | digitalWrite(5, HIGH); |
108 | digitalWrite(4, HIGH); |
109 | digitalWrite(3, HIGH); |
110 | digitalWrite(2, LOW); |
113 | digitalWrite(8, LOW); |
114 | digitalWrite(7, HIGH); |
115 | digitalWrite(6, HIGH); |
116 | digitalWrite(5, LOW); |
117 | digitalWrite(4, LOW); |
118 | digitalWrite(3, LOW); |
119 | digitalWrite(2, LOW); |
122 | digitalWrite(8, HIGH); |
123 | digitalWrite(7, HIGH); |
124 | digitalWrite(6, LOW); |
125 | digitalWrite(5, HIGH); |
126 | digitalWrite(4, HIGH); |
127 | digitalWrite(3, LOW); |
128 | digitalWrite(2, HIGH); |
131 | digitalWrite(8, HIGH); |
132 | digitalWrite(7, HIGH); |
133 | digitalWrite(6, HIGH); |
134 | digitalWrite(5, HIGH); |
135 | digitalWrite(4, LOW); |
136 | digitalWrite(3, LOW); |
137 | digitalWrite(2, HIGH); |
140 | digitalWrite(8, LOW); |
141 | digitalWrite(7, HIGH); |
142 | digitalWrite(6, HIGH); |
143 | digitalWrite(5, LOW); |
144 | digitalWrite(4, LOW); |
145 | digitalWrite(3, HIGH); |
146 | digitalWrite(2, HIGH); |
149 | digitalWrite(8, HIGH); |
150 | digitalWrite(7, LOW); |
151 | digitalWrite(6, HIGH); |
152 | digitalWrite(5, HIGH); |
153 | digitalWrite(4, LOW); |
154 | digitalWrite(3, HIGH); |
155 | digitalWrite(2, HIGH); |
158 | digitalWrite(8, HIGH); |
159 | digitalWrite(7, LOW); |
160 | digitalWrite(6, HIGH); |
161 | digitalWrite(5, HIGH); |
162 | digitalWrite(4, HIGH); |
163 | digitalWrite(3, HIGH); |
164 | digitalWrite(2, HIGH); |
167 | digitalWrite(8, HIGH); |
168 | digitalWrite(7, HIGH); |
169 | digitalWrite(6, HIGH); |
170 | digitalWrite(5, LOW); |
171 | digitalWrite(4, LOW); |
172 | digitalWrite(3, LOW); |
173 | digitalWrite(2, LOW); |
176 | digitalWrite(8, HIGH); |
177 | digitalWrite(7, HIGH); |
178 | digitalWrite(6, HIGH); |
179 | digitalWrite(5, HIGH); |
180 | digitalWrite(4, HIGH); |
181 | digitalWrite(3, HIGH); |
182 | digitalWrite(2, HIGH); |
185 | digitalWrite(8, HIGH); |
186 | digitalWrite(7, HIGH); |
187 | digitalWrite(6, HIGH); |
188 | digitalWrite(5, HIGH); |
189 | digitalWrite(4, LOW); |
190 | digitalWrite(3, HIGH); |
191 | digitalWrite(2, HIGH); |
195 | digitalWrite(pin, HIGH); |
Энкодер подключал по этой схеме:
Вал у меня такого размера, что 1 щелчок энкодера это 13мм.
Проблема следующая: При быстрой прокрутке (50см/сек), счетчик не успевает считать. При медленной прокрутке (10см/сек) считает идеально.
В чем может быть причина? Спасибо большое!
artur_fcsm, в коде. возьмите нормальный обработчик энкодера на прерываниях.
artur_fcsm, в коде. возьмите нормальный обработчик энкодера на прерываниях.
Спасибо! С вашим кодом энкодер работает на моного стабильнее и отлично выводит инфу через команду serial
Но после того, как я подключаю индикатор, через команду serial ничего не выходит (иероглифы)
Код:
001
#include <Encoder.h>
002
003
int
dig1, dig2, dig3, dig4=0;
// Цифры, которые будут последовательно вводиться
004
int
keys[10] = { 39, 30, 31, 32, 33, 34, 35, 36, 37, 38 };
// Массив с ASCII кодами цифер от 0 до 9 соответственно
005
int
s = 0;
006
unsigned
long
Counter = 0;
007
unsigned
long
k=0;
008
009
Encoder knobLeft(12, 13);
010
// avoid using pins with LEDs attached
011
012
void
setup
() {
013
Serial
.begin(9600);
014
Serial
.println(
"TwoKnobs Encoder Test:"
);
015
016
pinMode(2, OUTPUT);
// G
017
pinMode(3, OUTPUT);
// F
018
pinMode(4, OUTPUT);
// E
019
pinMode(5, OUTPUT);
// D
020
pinMode(6, OUTPUT);
// C
021
pinMode(7, OUTPUT);
// B
022
pinMode(8, OUTPUT);
// A
023
pinMode(9, OUTPUT);
// D4
024
pinMode(10, OUTPUT);
// D3
025
pinMode(11, OUTPUT);
// D2
026
pinMode(1, OUTPUT);
// D1
027
028
// Выключаем все сегменты:
029
digitalWrite(1, HIGH);
030
digitalWrite(11, HIGH);
031
digitalWrite(10, HIGH);
032
digitalWrite(9, HIGH);
033
delay(100);
// Пауза, чтобы «клавиатура» успела определиться в системе
034
}
035
036
long
positionLeft = -999;
037
038
void
loop
() {
039
long
newLeft;
040
newLeft = knobLeft.read();
041
if
(newLeft != positionLeft) {
042
Serial
.print(
"Left = "
);
043
Serial
.print(newLeft);
044
Serial
.println();
045
positionLeft = newLeft;
046
047
048
Counter = positionLeft*200;
// 131 микрометра
049
if
(Counter < 10000)
050
{
051
dig1=0; dig2=0; dig3=0; dig4=Counter/1000;
////
052
}
053
054
if
((Counter < 100000)&(Counter > 9999))
055
{
056
dig1=0; dig2=0; dig3=Counter / 10000; dig4=(Counter / 1000)%10 ;
057
}
058
if
((Counter < 1000000)&(Counter > 99999))
059
{
060
dig1=0; dig2=Counter / 100000; dig3=(Counter / 10000) % 10; dig4=(Counter / 1000)%10;
061
}
062
if
((Counter < 10000000)&(Counter > 999999))
063
{
064
dig1=Counter/10000000; dig2=(Counter / 100000) %10; dig3=(Counter / 10000) % 10; dig4=(Counter / 1000)%10;
065
}
066
digLED(1, dig1);
067
digLED(11, dig2);
068
digLED(10, dig3);
069
digLED(9, dig4);
070
}
071
}
072
073
void
digLED(
int
pin,
int
dig)
// Функция отображения цифер на индикаторе
074
{
075
076
digitalWrite(pin, LOW);
077
switch
(dig)
078
{
079
case
0:
080
digitalWrite(8, HIGH);
081
digitalWrite(7, HIGH);
082
digitalWrite(6, HIGH);
083
digitalWrite(5, HIGH);
084
digitalWrite(4, HIGH);
085
digitalWrite(3, HIGH);
086
digitalWrite(2, LOW);
087
break
;
088
case
1:
089
digitalWrite(8, LOW);
090
digitalWrite(7, HIGH);
091
digitalWrite(6, HIGH);
092
digitalWrite(5, LOW);
093
digitalWrite(4, LOW);
094
digitalWrite(3, LOW);
095
digitalWrite(2, LOW);
096
break
;
097
case
2:
098
digitalWrite(8, HIGH);
099
digitalWrite(7, HIGH);
100
digitalWrite(6, LOW);
101
digitalWrite(5, HIGH);
102
digitalWrite(4, HIGH);
103
digitalWrite(3, LOW);
104
digitalWrite(2, HIGH);
105
break
;
106
case
3:
107
digitalWrite(8, HIGH);
108
digitalWrite(7, HIGH);
109
digitalWrite(6, HIGH);
110
digitalWrite(5, HIGH);
111
digitalWrite(4, LOW);
112
digitalWrite(3, LOW);
113
digitalWrite(2, HIGH);
114
break
;
115
case
4:
116
digitalWrite(8, LOW);
117
digitalWrite(7, HIGH);
118
digitalWrite(6, HIGH);
119
digitalWrite(5, LOW);
120
digitalWrite(4, LOW);
121
digitalWrite(3, HIGH);
122
digitalWrite(2, HIGH);
123
break
;
124
case
5:
125
digitalWrite(8, HIGH);
126
digitalWrite(7, LOW);
127
digitalWrite(6, HIGH);
128
digitalWrite(5, HIGH);
129
digitalWrite(4, LOW);
130
digitalWrite(3, HIGH);
131
digitalWrite(2, HIGH);
132
break
;
133
case
6:
134
digitalWrite(8, HIGH);
135
digitalWrite(7, LOW);
136
digitalWrite(6, HIGH);
137
digitalWrite(5, HIGH);
138
digitalWrite(4, HIGH);
139
digitalWrite(3, HIGH);
140
digitalWrite(2, HIGH);
141
break
;
142
case
7:
143
digitalWrite(8, HIGH);
144
digitalWrite(7, HIGH);
145
digitalWrite(6, HIGH);
146
digitalWrite(5, LOW);
147
digitalWrite(4, LOW);
148
digitalWrite(3, LOW);
149
digitalWrite(2, LOW);
150
break
;
151
case
8:
152
digitalWrite(8, HIGH);
153
digitalWrite(7, HIGH);
154
digitalWrite(6, HIGH);
155
digitalWrite(5, HIGH);
156
digitalWrite(4, HIGH);
157
digitalWrite(3, HIGH);
158
digitalWrite(2, HIGH);
159
break
;
160
case
9:
161
digitalWrite(8, HIGH);
162
digitalWrite(7, HIGH);
163
digitalWrite(6, HIGH);
164
digitalWrite(5, HIGH);
165
digitalWrite(4, LOW);
166
digitalWrite(3, HIGH);
167
digitalWrite(2, HIGH);
168
break
;
169
}
170
delay(3);
171
digitalWrite(pin, HIGH);
172
173
}
Проблема возникает, когда я добавляю вот этот код:
1
digLED(1, dig1);
2
digLED(11, dig2);
3
digLED(10, dig3);
4
digLED(9, dig4);
Как мне кажется, проблема в спсобе вывода значения на индикатор.
Подскажит пожалуйста, в какую сторону копать. Спасибо!
Проблема возникает, когда я добавляю вот этот код:
1
digLED(1, dig1);
2
digLED(11, dig2);
3
digLED(10, dig3);
4
digLED(9, dig4);
Как мне кажется, проблема в спсобе вывода значения на индикатор.
Подскажит пожалуйста, в какую сторону копать. Спасибо!
Вы же на эти ноги энкодер подключили, судя по схеме... :) Посмотрите на строки 076 и 151 - в них пишется прямо в ногу, переданную для digLED, соответственно и порты энкодера коцаются.
Да нет, схема взята с интернета. Энкодер у меня подключен к ножкам 12 и 13
Да нет, схема взята с интернета. Энкодер у меня подключен к ножкам 12 и 13
А, так Вы же жалуетесь на пропадание вывода serial при подключении того куска... Та же проблема, что я предположил в прошлый раз: дёргаете вручную ногу 1, на котрой сериал сидит. :)
Да нет, схема взята с интернета. Энкодер у меня подключен к ножкам 12 и 13
А, так Вы же жалуетесь на пропадание вывода serial при подключении того куска... Та же проблема, что я предположил в прошлый раз: дёргаете вручную ногу 1, на котрой сериал сидит. :)
мда. действительно, мне не хватало ножек и я использовал ножку 1.
В итоге, у меня проблема, что ардуино пропускает импульсы от энкодера. 20 имп на оборот. Если крутить медленно - все ок. Если крутануть быстро, то от 20 остаётся 4-7 импульсов.
Что же я не так делаю (((
Да нет, схема взята с интернета. Энкодер у меня подключен к ножкам 12 и 13
А, так Вы же жалуетесь на пропадание вывода serial при подключении того куска... Та же проблема, что я предположил в прошлый раз: дёргаете вручную ногу 1, на котрой сериал сидит. :)
мда. действительно, мне не хватало ножек и я использовал ножку 1.
В итоге, у меня проблема, что ардуино пропускает импульсы от энкодера. 20 имп на оборот. Если крутить медленно - все ок. Если крутануть быстро, то от 20 остаётся 4-7 импульсов.
Что же я не так делаю (((
а) Вам уже советовали использовать библиотеку энкодера на прерываниях;
б) дребезг контактов, который оооочень зависит от качества энкодера, тоже необходимо учитывать программно или RC цепочкой.
а) Вам уже советовали использовать библиотеку энкодера на прерываниях;
б) дребезг контактов, который оооочень зависит от качества энкодера, тоже необходимо учитывать программно или RC цепочкой.
Я воспользовался советом:
1
void
loop
() {
2
long
newLeft;
3
newLeft = knobLeft.read();
4
if
(newLeft != positionLeft) {
5
Serial
.print(
"Left = "
);
6
Serial
.print(newLeft);
7
Serial
.println();
8
positionLeft = newLeft;
Или я что то не так понял?
Проблема была в delay
Проблема была в delay
Вот видите - и самостоятельно можете разобраться. Это очень хорошо! Теперь ёщё громодкий case замените на разумное, исползуя массив keys. :)
да. спасибо вам большое за помощь. Я уже многое изменил и убрал. Завтра выложу свой код.
Вот мой конечный вариант:
01
int
val;
02
int
encoder0PinA = 13;
03
int
encoder0PinB = 12;
04
unsigned
long
encoder0Pos = 0;
05
int
encoder0PinALast = LOW;
06
int
n = LOW;
07
08
const
int
numeral[10] = {
09
//ABCDEFG /dp
10
B11111100,
// 0
11
B01100000,
// 1
12
B11011010,
// 2
13
B11110010,
// 3
14
B01100110,
// 4
15
B10110110,
// 5
16
B00111110,
// 6
17
B11100000,
// 7
18
B11111110,
// 8
19
B11100110,
// 9
20
};
21
// pins for decimal point and each segment
22
// DP,G,F,E,D,C,B,A
23
const
int
segmentPins[] = { 13,2,3,4,5,6,7,8 };
24
//dig 0 1 2 3
25
const
int
digitPins[4] = { 1,11,10,9 };
26
27
unsigned
long
Counter = 0;
28
29
void
setup
() {
30
pinMode (encoder0PinA,INPUT);
31
pinMode (encoder0PinB,INPUT);
32
33
// Выключаем все сегменты:
34
digitalWrite(1, HIGH);
35
digitalWrite(11, HIGH);
36
digitalWrite(10, HIGH);
37
digitalWrite(9, HIGH);
38
delay(100);
// Пауза, чтобы «клавиатура» успела определиться в системе
39
40
for
(
int
i=1; i < 8; i++) {
41
pinMode(segmentPins[i], OUTPUT);
// set segment and DP pins to output
42
}
43
for
(
int
i=0; i < 4; i++) {
44
pinMode(digitPins[i], OUTPUT);
45
}
46
}
47
48
unsigned
long
positionLeft = 0;
49
50
void
loop
() {
51
n = digitalRead(encoder0PinA);
52
if
((encoder0PinALast == LOW) && (n == HIGH))
53
{
54
if
(digitalRead(encoder0PinB) == LOW)
55
{
56
encoder0Pos--;
57
}
else
{
58
encoder0Pos++;
59
}
60
}
61
encoder0PinALast = n;
62
Counter = (encoder0Pos * 900) / 10000 ;
63
showNumber(Counter);
64
}
65
66
void
showNumber(
long
number)
67
{
68
if
(number == 0)
69
{
70
showDigit( 0, 3);
71
}
72
else
73
{
74
for
(
int
digit = 3; digit >= 0; digit--) {
75
if
(number > 0)
76
{
77
showDigit( number % 10, digit) ;
78
number = number / 10;
79
}
80
}
81
}
82
}
83
84
void
showDigit(
int
number,
int
digit)
85
{
86
digitalWrite( digitPins[digit], LOW );
87
for
(
int
segment = 1; segment < 8; segment++)
88
{
89
boolean isBitSet = bitRead(numeral[number], segment);
90
digitalWrite( segmentPins[segment], isBitSet);
91
}
92
delayMicroseconds(750);
93
digitalWrite( digitPins[digit], HIGH );
94
}
Все отлично работает! Проверил! Отправил на производство.
Звонит заказчик, говорит счетчик считает сам по себе - я не поверил его словам. Поехал посмотреть сам.
И вот, что происходит. Когда включается станок - счетчик начинает самопроизвольно считать. И считает он только, когда запитан от БП 12В. Если он запитан от компа через usb, то все нормально. Что за чудеса?
Подскажите пожалуйста. БП менял.
Очевидно, помехи на входах. Это не совсем простая тема, чтобы дать точное и простое решение. Если учесть нормальную работу от БП нотбука, то можно сделать вывод, что энкодер не имеет электрического контакта с тем местом, куда установлен. Когда питаете от изолированного источника, наводкам, попадающим на жилу кабеля некуда стикать и, если эта же наводка не попадёт на другую жилу со сдвигом фазы, то она полетит дальше по своим делам, ничего не дав Вашему устройству. Когда включаете БП, он через общую сеть (через землю) даёт возможность помехам течь через вход на гальваническую свять с источником помехи - на землю. У Вас энкодер, как я полагаю, без всыких фильтров и защит включен в порт МК. Где Вы настраивали его входы в коде не видно, схемы тоже нет (или я забыл её). Если не использовали внутренние подтягивающие резистор и не ставили внешние, то в 10МОм вход МК может очень хорошо лететь помеха. В общем случае, необходимо отделить вход МК от энкодера резистором около 1кОм, приятнуть вход к земле или к VCC (в зависимости от того, куда второй конец энкодера подключен) резистором около 50кОм, и повесить конденсатор 0.1мкФ на землю, расположив его рядом со входом МК.