Требуется выводить информацию на 2 трёхразрядных семисегментных индикатора. Собрал схему: Спойлер: Схема Код: Спойлер: Код Код (C++): #include "math.h" #define DATA_PIN 13 // пин данных (англ. data) #define LATCH_PIN 12 // пин строба(защёлки) (англ. latch) #define CLOCK_PIN 11 // пин такта (англ. clock) #define DATA_PIN2 10 // пин данных (англ. data) #define LATCH_PIN2 9 // пин строба(защёлки) (англ. latch) #define CLOCK_PIN2 8 // пин такта (англ. clock) byte SegDisplay; // переменная для вывода символов на индикаторе byte RazrDisplay; // переменная для включения разрядов byte SegDisplay2; // переменная для вывода символов на индикаторе byte RazrDisplay2; // переменная для включения разрядов byte razryad[3]={127,191,223}; // массив цифр, указывающий разряды byte segments[12]= { // массив цифр, генерирующий из сегментов цифры 252, 96, 218, 242, // 0, 1, 2, 3 102, 182, 190, 224, // 4, 5, 6, 7 254, 246, 2, 0 }; // 8, 9, -, . int POT_PIN = A0; // потенциометр int POT_PIN2 = A2; // потенциометр void setup(){ pinMode(DATA_PIN, OUTPUT); // DATA_PIN выход pinMode(CLOCK_PIN, OUTPUT); // CLOCK_PIN выход pinMode(LATCH_PIN, OUTPUT); // LATCH_PIN выход pinMode(DATA_PIN2, OUTPUT); // DATA_PIN выход pinMode(CLOCK_PIN2, OUTPUT); // CLOCK_PIN выход pinMode(LATCH_PIN2, OUTPUT); // LATCH_PIN выход } void loop(){ int POT = analogRead(POT_PIN); int POT_NUMBER = map(POT, 0, 1023, 0, 120); int number = 0; // создаем переменную для вывода на экран number = POT_NUMBER; // Разбиваем цифру по разрядам индикатора if (number < 10){ // если наша цифра меньше 10, то Indicate(0, 11); // пишем в первый разряд пусто Indicate(1, 11); // пишем во второй разряд пусто Indicate(2, number); // пишем в третий разряд цифру } else if (number < 100){ // если наша цифра меньше 100, то Indicate(0, 11); // пишем в первый разряд пусто Indicate(1, number / 10); // пишем во второй разряд - цифру делёную на 10 Indicate(2, number % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } else { // если наша цифра меньше 1000, то Indicate(0, number / 100); // пишем в первый разряд - цифру делёную на 100 Indicate(1, (number % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10 Indicate(2, number % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } int POT2 = analogRead(POT_PIN2); int POT_NUMBER2 = map(POT2, 0, 1023, 0, 120); int number2 = 0; // создаем переменную для вывода на экран number2 = POT_NUMBER2; // Разбиваем цифру по разрядам индикатора if (number2 < 10){ // если наша цифра меньше 10, то Indicate2(0, 11); // пишем в первый разряд пусто Indicate2(1, 11); // пишем во второй разряд пусто Indicate2(2, number2); // пишем в третий разряд цифру } else if (number2 < 100){ // если наша цифра меньше 100, то Indicate2(0, 11); // пишем в первый разряд пусто Indicate2(1, number2 / 10); // пишем во второй разряд - цифру делёную на 10 Indicate2(2, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } else { // если наша цифра меньше 1000, то Indicate2(0, number2 / 100); // пишем в первый разряд - цифру делёную на 100 Indicate2(1, (number2 % 100) / 10);// пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10 Indicate2(2, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } } void Indicate(int r,int x){ SegDisplay=segments[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре. RazrDisplay=razryad[r]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре. digitalWrite(LATCH_PIN, LOW); // устанавливаем синхронизацию "защелки" на LOW shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, SegDisplay); // Записываем информацию для первого регистра (Номер символа) digitalWrite(LATCH_PIN, HIGH); // "защелкиваем" регистр, тем самым устанавливая значения на выходах delayMicroseconds(2500); // пауза, чтобы сегменты "разгорелись" } void Indicate2(int r2,int x2){ SegDisplay2=segments[x2]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре. RazrDisplay2=razryad[r2]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре. digitalWrite(LATCH_PIN2, LOW); // устанавливаем синхронизацию "защелки" на LOW shiftOut(DATA_PIN2, CLOCK_PIN2, LSBFIRST, RazrDisplay2);// Записываем информацию для второго регистра (Номер разряда) shiftOut(DATA_PIN2, CLOCK_PIN2, LSBFIRST, SegDisplay2); // Записываем информацию для первого регистра (Номер символа) digitalWrite(LATCH_PIN2, HIGH); // "защелкиваем" регистр, тем самым устанавливая значения на выходах delayMicroseconds(2500); // пауза, чтобы сегменты "разгорелись" } С таким кодом на обоих индикаторах тускло горят 2 и 3 разряды,1 разряд на обоих нормально, мерцание пропало после установки задержки в 2.5 миллисекунды после функций indicate. Спойлер: Индикатор Если задержку в одной из функций убрать, то нормально работает идникатор, в функции которого задержка осталась, что можно сделать?
Попробуйте организовать вывод на индикаторы следующим образом: вывод в первый сегмент обоих индикаторов Indicate1(0, XX) & Indicate2(0, XX); небольшая задержка; вывод во второй сегмент обоих индикаторов Indicate1(1, XX) & Indicate2(1, XX); небольшая задержка; вывод в третий сегмент обоих индикаторов Indicate1(2, XX) & Indicate2(2, XX); небольшая задержка. И, если есть возможность, функционал опроса датчиков лучше вынести в отдельный поток -- вывод на индикаторы оставить в 'loop()', а опрос организовать через таймер.
Включил все регистры последовательно, так наверно проще даже будет: Спойлер: Схема Изменил функцию: Спойлер: Скетч Код (C++): #include "math.h" #define DATA_PIN 13 // пин данных (англ. data) #define LATCH_PIN 12 // пин строба(защёлки) (англ. latch) #define CLOCK_PIN 11 // пин такта (англ. clock) byte SegDisplay; // переменная для вывода символов на индикаторе byte RazrDisplay; // переменная для включения разрядов byte razryad[3]={127,191,223}; // массив цифр, указывающий разряды byte segments[12]= { // массив цифр, генерирующий из сегментов цифры 252, 96, 218, 242, // 0, 1, 2, 3 102, 182, 190, 224, // 4, 5, 6, 7 254, 246, 2, 0 }; // 8, 9, -, . int POT_PIN = A2; // потенциометр int POT_PIN2 = A0; // потенциометр void setup(){ pinMode(DATA_PIN, OUTPUT); // DATA_PIN выход pinMode(CLOCK_PIN, OUTPUT); // CLOCK_PIN выход pinMode(LATCH_PIN, OUTPUT); // LATCH_PIN выход } void loop(){ int POT = analogRead(POT_PIN); int POT_NUMBER = map(POT, 0, 1023, 0, 120); int number = 0; number = POT_NUMBER; int POT2 = analogRead(POT_PIN2); int POT_NUMBER2 = map(POT2, 0, 1023, 0, 120); int number2 = 0; number2 = POT_NUMBER2; if (number < 10 or number2 <10){ // если наша цифра меньше 10, то Indicate(0, 11, 11); // пишем в первый разряд пусто Indicate(1, 11, 11); // пишем во второй разряд пусто Indicate(2, number, number2); // пишем в третий разряд цифру } else if (number < 100 or number2 < 100){ // если наша цифра меньше 100, то Indicate(0, 11, 11); // пишем в первый разряд пусто Indicate(1, number / 10, number2 / 10); // пишем во второй разряд - цифру делёную на 10 Indicate(2, number % 10, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } else { // если наша цифра меньше 1000, то Indicate(0, number / 100, number2 / 100); // пишем в первый разряд - цифру делёную на 100 Indicate(1, (number % 100) / 10, (number2 % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10 Indicate(2, number % 10, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } } void Indicate(int r, int x, int r2){ digitalWrite(LATCH_PIN, LOW); // устанавливаем синхронизацию "защелки" на LOW shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, razryad[r]); // Записываем информацию для второго регистра (Номер разряда) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, segments[x]); // Записываем информацию для первого регистра (Номер символа) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, razryad[r]); // Записываем информацию для второго регистра (Номер разряда) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, segments[r2]); // Записываем информацию для первого регистра (Номер символа) digitalWrite(LATCH_PIN, HIGH); // "защелкиваем" регистр, тем самым устанавливая значения на выходах delayMicroseconds(5); // пауза, чтобы сегменты "разгорелись" } Теперь, чтобы горели 2 разряда на одном из индикаторов нужно и на втором включать 2 разряда, чтобы 3 разряда горели, нужно чтобы и на втором 3 разряда горело, иначе показывает ерунду. На сколько я понимаю проблема в цикле Спойлер: Цикл Код (C++): if (number < 10 or number2 <10){ // если наша цифра меньше 10, то Indicate(0, 11, 11); // пишем в первый разряд пусто Indicate(1, 11, 11); // пишем во второй разряд пусто Indicate(2, number, number2); // пишем в третий разряд цифру } else if (number < 100 or number2 < 100){ // если наша цифра меньше 100, то Indicate(0, 11, 11); // пишем в первый разряд пусто Indicate(1, number / 10, number2 / 10); // пишем во второй разряд - цифру делёную на 10 Indicate(2, number % 10, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } else { // если наша цифра меньше 1000, то Indicate(0, number / 100, number2 / 100); // пишем в первый разряд - цифру делёную на 100 Indicate(1, (number % 100) / 10, (number2 % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10 Indicate(2, number % 10, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } В программировании я не силён, что можно с этим сделать?
Вы в оба разрядных регистра запихиваете одни и те же данные, естественно зажигаться будут оба индикатора. Несколько замечаний: 1) Электрическое. Обратите внимание на допустимый ток вывода регистра и на допустимый суммарный ток через вывод GND самого регистра, куда у вас подключены GNDn от индикаторов. В этом месте стоит подключать индикаторы не напрямую к регистрам, а через транзисторы (полевик типа 2N7000/2N7002 сойдет). 2) Количество регистров можно сократить до 3-х, поскольку у вас 6 сегментов, для управления разрядами достаточно одного регистра. 3) Программное. Поскольку в процессе индикации данные не меняются, вычисляйте содержимое массивов один раз заранее, а потом уже выводите. Ну и ... razryad называется digit
На сколько я понял нужно сделать так: Спойлер: скетч Код (C++): #include "math.h" #define DATA_PIN 13 // пин данных (англ. data) #define LATCH_PIN 12 // пин строба(защёлки) (англ. latch) #define CLOCK_PIN 11 // пин такта (англ. clock) byte SegDisplay; // переменная для вывода символов на индикаторе byte RazrDisplay; // переменная для включения разрядов byte SegDisplay2; // переменная для вывода символов на индикаторе byte RazrDisplay2; // переменная для включения разрядов byte razryad[3]={127,191,223}; // массив цифр, указывающий разряды byte segments[12]= { // массив цифр, генерирующий из сегментов цифры 252, 96, 218, 242, // 0, 1, 2, 3 102, 182, 190, 224, // 4, 5, 6, 7 254, 246, 2, 0 }; // 8, 9, -, . int POT_PIN = A2; // потенциометр int POT_PIN2 = A0; // потенциометр void setup(){ pinMode(DATA_PIN, OUTPUT); // DATA_PIN выход pinMode(CLOCK_PIN, OUTPUT); // CLOCK_PIN выход pinMode(LATCH_PIN, OUTPUT); // LATCH_PIN выход Serial.begin(9600); } void loop(){ int POT = analogRead(POT_PIN); int POT_NUMBER = map(POT, 0, 1023, 0, 121); POT_NUMBER = constrain(POT_NUMBER, 1, 120); int number = 0; number = POT_NUMBER; int POT2 = analogRead(POT_PIN2); int POT_NUMBER2 = map(POT2, 0, 1023, 0, 121); POT_NUMBER2 = constrain(POT_NUMBER2, 1, 120); int number2 = 0; number2 = POT_NUMBER2; if (number < 10 or number2 < 10){ // если наша цифра меньше 10, то Indicate(0, 11, 0, 11); // пишем в первый разряд пусто Indicate(1, 11, 1, 11); // пишем во второй разряд пусто Indicate(2, number, 2, number2); // пишем в третий разряд цифру } else if (number < 100 or number2 < 100){ // если наша цифра меньше 100, то Indicate(0, 11, 0, 11); // пишем в первый разряд пусто Indicate(1, number / 10, 1, number2 / 10); // пишем во второй разряд - цифру делёную на 10 Indicate(2, number % 10, 2, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } else { // если наша цифра меньше 1000, то Indicate(0, number / 100, 0, number2 / 100); // пишем в первый разряд - цифру делёную на 100 Indicate(1, (number % 100) / 10, 1, (number2 % 100) / 10); // пишем во второй разряд - цифру цифру оставшуюся от деления на 100 делённую на 10 Indicate(2, number % 10, 2, number2 % 10); // пишем в третий разряд - цифру цифру оставшуюся от деления на 10 } } void Indicate(int r, int x, int r2, int x2){ SegDisplay = segments[x]; RazrDisplay = razryad[r]; SegDisplay2 = segments[x2]; RazrDisplay2 = razryad[r2]; digitalWrite(LATCH_PIN, LOW); // устанавливаем синхронизацию "защелки" на LOW shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, SegDisplay); // Записываем информацию для первого регистра (Номер символа) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, RazrDisplay2); // Записываем информацию для второго регистра (Номер разряда) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, SegDisplay2); // Записываем информацию для первого регистра (Номер символа) digitalWrite(LATCH_PIN, HIGH); // "защелкиваем" регистр, тем самым устанавливая значения на выходах delay(5); // пауза, чтобы сегменты "разгорелись" } Но ничего не изменилось!
Вы не там изменили код. Смысл замечания был в том, что не нужно в loop() каждый раз бить число на разряды. Поскольку у вас цикл динамической индикации зачем-то перемешан с главным циклом (измерение-индикация-управление), то данные каждый раз другие. Динамическую индикацию нужно выносить в отдельные функции. Например, RefreshDisplay() должна вызываться по таймеру из обработчика прерывания и тупо выбрасывать буфер дисплея в регистры, а UpdateDisplay(int n) бить число n на разряды и заполнять буфер дисплея новыми данными. UpdateDisplay(n) уже может вызываться из главного цикла или любого другого места асинхронно для обновления данных дисплея.