Подключение 4-х разрядного семисегментного индикатора
- Войдите на сайт для отправки комментариев
Здравствуйте, уважаемы форумчане!
Я у вас тут новеньки, начинающий. В коде пока не особо разбираюсь, так что прошу помощи.
Есть семисегментник. К ардуино подцепил, работает прекрасно, но как всегда есть "но".
Код:
uint8_t buf[8] = { 0 }; // байт с информацией о «нажатой» клавише
void setup()
{
Serial.begin(9600); // Устанавливаем скорость соединения
pinMode(2, OUTPUT); // G
pinMode(3, OUTPUT); // F
pinMode(4, OUTPUT); // E
pinMode(5, OUTPUT); // D
pinMode(6, OUTPUT); // C
pinMode(7, OUTPUT); // B
pinMode(8, OUTPUT); // A
pinMode(9, OUTPUT); // D4
pinMode(10, OUTPUT); // D3
pinMode(11, OUTPUT); // D2
pinMode(12, OUTPUT); // D1
// Так как модуль сегментных индикаторов имеет общий анод, то для того, чтобы
// светился сегмент, вывод Arduino должно быть в высокоимпедансном состоянии
// и наоборот
// Выключаем все сегменты:
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
digitalWrite(9, HIGH);
delay(2000); // Пауза, чтобы «клавиатура» успела определиться в системе
}
void loop()
{
int dig1, dig2, dig3, dig4; // Цифры, которые будут последовательно вводиться
int keys[10] = { 39, 30, 31, 32, 33,
34, 35, 36, 37, 38 }; // Массив с ASCII кодами цифер от 0 до 9 соответственно
// Перебор с 0000 до 9999:
for(dig1=0; dig1<10; dig1++)
{
for(dig2=0; dig2<10; dig2++)
{
for(dig3=0; dig3<10; dig3++)
{
for(dig4=0; dig4<10; dig4++)
{
pressKey(keys[dig1]);
pressKey(keys[dig2]);
pressKey(keys[dig3]);
pressKey(keys[dig4]);
pressKey(40); // Клавиша Enter
// Текущий пароль будет отображаться в течение примерно 15-ти секунд (чуть больше времени задержки ввода)
for(int i=0; i<1200; i++)
{
digLED(12, dig1);
digLED(11, dig2);
digLED(10, dig3);
digLED(9, dig4);
}
}
}
}
}
}
void pressKey(int dig) // Функция ввода
{
buf[2] = dig;
Serial.write(buf, 8); // Нажать клавишу
buf[0] = 0;
buf[2] = 0;
delay(20);
Serial.write(buf, 8); // Отпустить клавишу
delay(300);
}
// Возможно, существуют библиотеки для сегментных индикторов, но мне не захотелось с ними разбираться,
// поэтому набросал свой алгоритм обхода сегментов индикатора
void digLED(int pin, int dig) // Функция отображения цифер на индикаторе
{
digitalWrite(pin, LOW);
switch(dig)
{
case 0:
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(3, LOW);
digitalWrite(2, HIGH);
break;
case 1:
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);
digitalWrite(3, HIGH);
digitalWrite(2, HIGH);
break;
case 2:
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, HIGH);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(3, HIGH);
digitalWrite(2, LOW);
break;
case 3:
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, HIGH);
digitalWrite(3, HIGH);
digitalWrite(2, LOW);
break;
case 4:
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
break;
case 5:
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, HIGH);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
break;
case 6:
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
break;
case 7:
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, HIGH);
digitalWrite(4, HIGH);
digitalWrite(3, HIGH);
digitalWrite(2, HIGH);
break;
case 8:
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, LOW);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
break;
case 9:
digitalWrite(8, LOW);
digitalWrite(7, LOW);
digitalWrite(6, LOW);
digitalWrite(5, LOW);
digitalWrite(4, HIGH);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
break;
}
delay(3);
digitalWrite(pin, HIGH);
}
Индикатор с общим катодом (код под общий анод), соответственно поменял значения HIGH на LOW и наоборот. Подключил, и вместо ожидаемого результата (а должен он показывать значения начиная с 0000 до 9999) получилось так, что на всех сегментах загорается одинаковое число. Считалка идет так : 1111, 2222 и т.д. Потом снова по кругу. Код взят из статьи про брутфорс, индикатор там был модульный, с матричной разводкой и отдельным пином под питание. У меня же обычный 12-пиновый. Что нужно поменять в этом коде, чтобы все заработало так, как задумывалось?
Заранее огромное спасибо всем ответившим.
Что-то я не понял, Вы бы как-то понятнее объяснили. Он у Вас
работает прекрасно
или
Считалка идет так : 1111, 2222 и т.д. Потом снова по кругу.
Как-то одновременно эти два высказывания не могут быть истинными.
Так как?
Т.е. все сегменты горят. Выразился не так.
Ну, в общем, комментарием в строке 19 про "высокоимпедансное" состояние Вы изоядно повеселили. Постарайтесь не употреблять слов, значения которых не знаете.
А по сути, динамическая индикация делается не совсем так. Вернее, совсем не так.
Вот Вы можете объяснить словами что именно Вы делаете? Попробуйте описать. Просто словами.
Все дело в том, что код не мой. Взят из статьи на хабре. Сам в кодостроении профан. Если бы знал, как заставить эту схему "шуршать" как надо - думаю, сюда не обратился бы. Вкратце - контроллер сейчас эмулирует клавиатуру. Нужно сделать так, чтобы в момент ввода числа на компьютере, на индикаторе отображалось вводимое число. Т.е. как я понял нужно штудировать статьи про динамическую индикацию? Или есть какие-то готовые скетчи с таким принципом работы?
З.Ы. - Просто одни очень нехорошие люди залочили мак. Нужен для работы, поэтому пытаюсь вот таким вот образом осуществить перебор паролей. В сервис обращаться жаба душит, да и ближайший в 300 километрах от дома.
В общем, вот в этой теме, я другому новичку, наверное с пару недель рассказывал как работать с динамической индикацией. Сначала в простейшем случае. потом дошли до использования таймеров (с апрвилами их расчёта) и виртуальных экранов. Причём обсуждалась и схема и программа. Почитайте. Букв там много, но это полезно. Например, он там по ходу задавал вопросы. которые наверняка и у Вс возникнут. Думаю, прочитав ту тему, как-нибудь разберётесь.
Огромное Вам спасибо!
Добрый день, Евгений!
Читал я тему. Понял то, что ничего не понял. Видимо, для меня это темный лес. Скетч с "Велосипедом" под 4 разряда переделать только смог. Времени свободного как такового нет, да и домашний ноутбук в вечных разъездах. Если немного видоизменить код с велосипедом - заработает? И как это реализовать?
Так велосипед у Вас работает?
Там ведь есть функция putNumber, которая позволяет любое число выводить. Она там в строке 146 используется. Так что можете выводить числа, а не только педали крутить.
А в чём Вам нужна переделка?
Нужно, чтобы он выполнял те же функции, что и код в начале темы. Т.е. последовательно вводил числа от 0000 до 9999 с интервалом в 15 секунд и, соответственно, отображал вводимое число на индикаторе. Как я понял, в исходном коде за это отвечает часть:
// Перебор с 0000 до 9999: for(dig1=0; dig1<10; dig1++) { for(dig2=0; dig2<10; dig2++) { for(dig3=0; dig3<10; dig3++) { for(dig4=0; dig4<10; dig4++) { pressKey(keys[dig1]); pressKey(keys[dig2]); pressKey(keys[dig3]); pressKey(keys[dig4]); pressKey(40); // Клавиша Enter // Текущий пароль будет отображаться в течение примерно 15-ти секунд (чуть больше времени задержки ввода) for(int i=0; i<1200; i++) { digLED(12, dig1); digLED(11, dig2); digLED(10, dig3); digLED(9, dig4); } } } } } } void pressKey(int dig) // Функция ввода { buf[2] = dig; Serial.write(buf, 8); // Нажать клавишу buf[0] = 0; buf[2] = 0; delay(20); Serial.write(buf, 8); // Отпустить клавишу delay(300); }Ну, так и делайте
for (int n = 0; n < 10000; n++) { pressKey(n / 1000); // cамая старшая (левая) цифра) pressKey((n / 100) % 10); // Вторая цифра слева pressKey((n / 10) % 10); // Третья цифра слева pressKey(n % 10); // Самая правая цифра putNumber(n); // Показ числа на индикаторе }Вроде, больше ничего не надо. Фунцкия putNumber определена в скетче велосипеда.
Здесь? Для вывода тысяч нужно что? Или можно её упростить?
// Функция разделяет число на сотни, десятки и единицы и складывает в массив масок // сотни в позицию 2 // десятки в позицию 1 // единицы в позицию 0 // void putNumber(const unsigned number) { static const uint8_t allDigits[] = { D0, D1, D2, D3, D4, D5, D6, D7, D8, D9 }; div_t divRes = div(number, 100); putMask(allDigits[divRes.quot], 2); divRes = div(divRes.rem, 10); putMask(allDigits[divRes.quot], 1); putMask(allDigits[divRes.rem], 0); }И в каком месте кода её расположить? Будет ли 15-секундная задержка? Прошу прощения за такое количесвто вопросов.
Не, ну саму функцию-то не трогайте, она нормальная.
Вы мне не ответили на ворос, у Вас велосипед работает? Мне надо от чего-то отталкиваться.
Он (велосипед) вообще-то на трёхразрядный индикатор, а у Вас четырёхразрядный, Вы его уже переделали, он работает?
Велосипед работает на последних трех разрядах. На первом постоянно горит средний сегмент и мерцают верхний и нижний.
Евгений! Дико извиняюсь что отнял часть Вашего времени. Всё оказалось куда проще, чем казалось на первый взгляд. В коде, который я изначально скидывал, я допустил одну ошибку. А именно:
// Возможно, существуют библиотеки для сегментных индикторов, но мне не захотелось с ними разбираться, // поэтому набросал свой алгоритм обхода сегментов индикатора void digLED(int pin, int dig) // Функция отображения цифер на индикаторе { digitalWrite(pin, LOW); switch(dig) { case 0: digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW); break; case 1: digitalWrite(8, LOW); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW); break; case 2: digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, HIGH); break; case 3: digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH); break; case 4: digitalWrite(8, LOW); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH); break; case 5: digitalWrite(8, HIGH); digitalWrite(7, LOW); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH); break; case 6: digitalWrite(8, HIGH); digitalWrite(7, LOW); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH); break; case 7: digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW); break; case 8: digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH); break; case 9: digitalWrite(8, HIGH); digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH); break; } delay(3); digitalWrite(pin, HIGH); }В этой части кода абсолютно все значения LOW и HIGH поменял на противоположные. Как теперь понял - не нужно было трогать digitalWrite (pin, LOW) и digitalWrite (pin, HIGH) в начале и в конце. В оригинальном коде значения стояли HIGH и LOW соответственно. Поменял - и все заработало. И все равно огромное Вам спасибо! Подогрели интерес к Arduino.)
Последний вопрос: Какие резисторы ставить на индикатор? Везде пишут по-разному. Где-то номиналом 100 Ом, где-то 1кОм, где-то только на пины разрядов, а где-то на все пины. Вы бы что посоветовали? Светодиоды на индикаторе красного цвета.
http://forum.cxem.net/index.php?/topic/41584-%D0%BE-%D1%81%D0%B2%D0%B5%D...
Но Вы не обльщайтесь. Работать это будет криво. Ни с того, ни с сего будет мерцать экран. Хотите нормально - делайте через таймеры, дожмите велосипед, например.
Про резисторы. Я что-то не помню Вашей схемы. Давайте схему - поговорим о резисторах.
Там есть два типа резисторов - персональные на каждый сегмент. И резисторы в базах транзисторов, которые стоят на цифрах (надеюь, у Вас стоят транзисторы на цифрах?) Вас какие резисторы иетерсуют? Ну, и схему давайте.
Сейчас счетчик до 100 прогнал - мерцаний пока не заметил. Схемы, в принципе нет. Сразу с выходов ардуино на индикатор. Думаю, за это меня отругают.)
P.S. - числа на индикаторе меняются так: 0000 => Гаснет => 0001 => Гаснет и т.д. По сути мне сейчас нужно ардуино не спалить и индикатор.
У вас самый большой минус программы. Ардуина работает только на индикатор. А вот если вы захотите сделать какое-то устройство, то будут траблы. Отображение должно быть или реализовано аппаратно, или программно в фоне. И повесте резисторы на a,b,c ...h - 100 ом -1к
Мне пока только это и нужно. Плюсом клавиатуру эмулирует, что как раз подходит для моей задачи.) Резисторы только на сегменты вешать? На разряды не нужны?
Что цифры (общие выводы) идут прямо на ноги ардуины?
Как, у Вас вообще никаких нет? Блин, стойкая Вам ардуина попадась. Другая бы давно сдохла.
Что делать я Вам сказал в прошлом посте.
Резисторы нашёл на 100 Ом и на 1 кОм. По десятку каждых набралось.
Написал тоже свою программу. Но у меня видно бракованый индикатор, пришлось ужать до одиночного. Он у меня оказался.
/* 4 разрядный 7сегметный индикатор SH5461AS 12-D3 11-a 10-f 9-D2 8-D1 7-b 1-e 2-d 3-dp 4-c 5-g 6-D0 11 - a ( a_pin) 1 горит 0 нет 7 - b ( b_pin) 4 - c ( c_pin) 2 - d ( d_pin) 1 - e ( e_pin) 10 - f ( f_pin) 5 - g ( g_pin) 3 - dp(dp_pin) 6 -D0 (D0_pin) 0 горит 1 нет 8 -D1 (D1_pin) 9 -D2 (D2_pin) 12 -D3 (D3_pin) */ //#1 uint8_t Count; // счетчик //#2 const int e_pin =2 ;// нога 1 SH5461AS const int d_pin =3 ;// нога 2 SH5461AS const int dp_pin=4 ;// нога 3 SH5461AS const int c_pin =5 ;// нога 4 SH5461AS const int g_pin=6 ;// нога 5 SH5461AS const int D0_pin=7 ;// нога 6 SH5461AS const int D3_pin=8 ;// нога 12 SH5461AS const int a_pin =9 ;// нога 11 SH5461AS const int f_pin =10;// нога 10 SH5461AS const int D2_pin=11;// нога 9 SH5461AS const int D1_pin=12;// нога 8 SH5461AS const int b_pin =13;// нога 7 SH5461AS // Вывод числа на экран void WriteNumber(int Number) { WriteNumberToSegment(0 , Number / 1000); WriteNumberToSegment(1 , (Number / 100) % 10); WriteNumberToSegment(2 , (Number / 10) % 10); WriteNumberToSegment(3 , Number % 10); } // запись нужного числа (0-9) в нужную позицию(1-4) void WriteNumberToSegment(byte Segment, byte Value){ Out_segment(Segment); Out_Number(Value); } // матрица выбора знакоместа 1 to 4 const byte SEGMENT_SELECT[] = { B11110111, // D4 B11111011, // D2 B11111101, // D1 B11111110};// D0 void Out_segment(byte Segment){ digitalWrite(D0_pin,SEGMENT_SELECT[Segment]&0x08); digitalWrite(D1_pin,SEGMENT_SELECT[Segment]&0x04); digitalWrite(D2_pin,SEGMENT_SELECT[Segment]&0x02); digitalWrite(D3_pin,SEGMENT_SELECT[Segment]&0x01); } // матрица цифр 0 to 9 const byte SEGMENT_MAP[] = { B00111111,// 0 B00000110,//1 B01011011,//2 B01001111,//3 B01100110,//4 B01101101,//5 B01111100,//6 B00000111,//7 B01111111,//8 B01100111};//9 void Out_Number(byte Number){ digitalWrite(dp_pin,SEGMENT_MAP[Number]&0x80); digitalWrite(g_pin,SEGMENT_MAP[Number]&0x40); digitalWrite(f_pin,SEGMENT_MAP[Number]&0x20); digitalWrite(e_pin,SEGMENT_MAP[Number]&0x10); digitalWrite(d_pin,SEGMENT_MAP[Number]&0x08); digitalWrite(c_pin,SEGMENT_MAP[Number]&0x04); digitalWrite(b_pin,SEGMENT_MAP[Number]&0x02); digitalWrite(a_pin,SEGMENT_MAP[Number]&0x01); } void setup() { //#1 Count = 0; //#2 pinMode(a_pin, OUTPUT); pinMode(b_pin, OUTPUT); pinMode(c_pin, OUTPUT); pinMode(d_pin, OUTPUT); pinMode(e_pin, OUTPUT); pinMode(f_pin, OUTPUT); pinMode(D0_pin, OUTPUT); pinMode(D1_pin, OUTPUT); pinMode(D2_pin, OUTPUT); pinMode(D3_pin, OUTPUT); pinMode( g_pin, OUTPUT); pinMode(dp_pin, OUTPUT); } void loop() { static uint32_t MILLIS ; MILLIS = millis() ; //#1 100 милисек счетчик static uint32_t future1 = 0 ; if (MILLIS >= future1) { future1 = MILLIS + 100 ; Count++; if(Count > 9999) Count = 0; } //#2 WriteNumber(Count); }ПС: Может кому-то поможет.
А вот для одиночного
/* 7сегметный индикатор 5161as 10-g 9-f 8-D0 7-a 6-b 1-e 2-d 3-D0 4-c 5-dp 5161as a ( a_pin) 1 горит 0 нет b-> ( b_pin) c->4 ( c_pin) d->3 ( d_pin) e->2 ( e_pin) f->7 ( f_pin) g->6 ( g_pin) dp->5(dp_pin) D0 ->GND */ //#1 uint8_t Count; // счетчик //#2 const int e_pin =2 ;// нога 1 5161AS const int d_pin =3 ;// нога 2 5161AS const int c_pin =4 ;// нога 4 5161AS const int dp_pin=5 ;// нога 5 5161AS const int g_pin=6 ;// нога 10 5161AS const int f_pin =7 ;// нога 9 5161AS const int a_pin =8 ;// нога 7 5161AS const int b_pin =9 ;// нога 6 5161AS // матрица цифр 0 to 9 const byte SEGMENT_MAP[] = { B00111111,// 0 B00000110,//1 B01011011,//2 B01001111,//3 B01100110,//4 B01101101,//5 B01111100,//6 B00000111,//7 B01111111,//8 B01100111};//9 void Write_Number(byte Value){ digitalWrite(dp_pin,SEGMENT_MAP[Value]&0x80); digitalWrite(g_pin ,SEGMENT_MAP[Value]&0x40); digitalWrite(f_pin ,SEGMENT_MAP[Value]&0x20); digitalWrite(e_pin ,SEGMENT_MAP[Value]&0x10); digitalWrite(d_pin ,SEGMENT_MAP[Value]&0x08); digitalWrite(c_pin ,SEGMENT_MAP[Value]&0x04); digitalWrite(b_pin ,SEGMENT_MAP[Value]&0x02); digitalWrite(a_pin ,SEGMENT_MAP[Value]&0x01); } void setup() { //#1 Count = 0; //#2 pinMode(a_pin, OUTPUT); pinMode(b_pin, OUTPUT); pinMode(c_pin, OUTPUT); pinMode(d_pin, OUTPUT); pinMode(e_pin, OUTPUT); pinMode(f_pin, OUTPUT); pinMode( g_pin, OUTPUT); pinMode(dp_pin, OUTPUT); } void loop() { static uint32_t MILLIS ; MILLIS = millis() ; //#1 500 милисек счетчик static uint32_t future1 = 0 ; if (MILLIS >= future1) { future1 = MILLIS + 500 ; Count++; if(Count > 9) Count = 0; } //#2 Write_Number(Count); }