Отображение двоичных данных на светодиодах
Я написал программу для Arduino UNO и 3 светодиодных лампочек. Программа должна преобразовывать введенное число в двоичное, а затем отображать его на светодиодах, вкл. - 1, выкл. - 0. Я просматривал ее довольно много раз и не понимаю, почему она не работает так, как должна. Я новичок в работе с Arduino, поэтому мне, вероятно, просто нужен более опытный взгляд, чтобы показать мне, где я накосячил. Ниже у меня есть ссылка на изображение настройки Arduino. Спасибо! https://drive.google.com/file/d/0B8k_WNZ3eFOkZHkwNUllTEp4WGM/view?usp=sharing
//настройка освещения
const int lightOne = 13;
const int lightTwo = 12;
const int lightThree = 11;
//массив огней для печати двоичного кода
int lights[] = {lightOne, lightTwo, lightThree};
void setup() {
//установка режимов выводов и запуск последовательного монитора
pinMode(lightOne, OUTPUT);
pinMode(lightTwo, OUTPUT);
pinMode(lightThree, OUTPUT);
Serial.begin(9600);
}
//преобразует заданное число в двоичное
String binary(int number) {
String r;
while(number!=0) {
r = (number % 2 == 0 ? "0" : "1")+r;
number /= 2;
}
return r;
}
//выводит двоичную строку на индикаторы (не ожидая чисел больше 9)
void printBinary(String binaryNumber) {
for (int i = 0; i < sizeof(binaryNumber); i++) {
digitalWrite(lights[i+11], (binaryNumber[i] == '0' ? LOW : HIGH));
delay(2000);
}
}
void loop() {
int input = Serial.read(); //получить число
String binaryNumber = binary(input); //преобразовать число в двоичное
Serial.println(binaryNumber); //вывести двоичный код на последовательный монитор
printBinary(binaryNumber); //отображение числа в двоичном виде на светодиодах
}
@Jamerack, 👍2
3 ответа
Лучший ответ:
Добро пожаловать в SE Arduino!
Длинная версия
Вам нужно обратить внимание на несколько вещей:
- Не используйте класс
String
, он слишком нагружает Arduino. - Ваша функция преобразования на самом деле не нужна, поскольку вы можете преобразовать ее в
Serial.println()
, указавbinary
в качестве выходных данных. Например: <code>Serial.println(number, BIN)</code>; Serial.read
возвращает целое число, но этотint
в любом случае содержит только <code>byte</code> (беззнаковое) значение (если только нечего читать, в таком случае он возвращает-1
). Поскольку вы принимаете число (на самом деле не имеет значения) и хотите, чтобы оно было числом при возврате, просто используйтеint
илиbyte
(беззнаковое:0 <-> 255
) или <code>char</code> (со знаком:-127 <-> +128
).- Вы можете/должны/не имеет значения, используете ли вы
Serial.available()
или нет, это ваше дело, я обычно так делаю, но это в любом случае неблокируемо, и если там нечего читать, то он просто продолжит работу. Хотя, если вы не собираетесь его использовать, вам следует проверить на-1
, поскольку то, что вы делаете в данный момент, это берете это и преобразуете в двоичный код (который равен0xFF
, что означает все включено). Это одна из ваших основных проблем в коде (другая находится в разделе Короткая версия. - Вы используете
"0"
и"1"
, которые являются значениямиASCII
, и вы не указали, как вы получаете число. Так что это может бытьASCII
(byte
) или на самом деле значениеbyte
. т. е."0"
это48 (dec)
или30 (hex)
. Тогда как0
это простоноль
. Достаточно забавно, что поскольку вы используете остаток от деления (%
), это на самом деле не имеет значения, потому что вас интересует только младший полубайт, который для вашего кода не имеет значения, что закодировано в старшем конце. например:1
(0b00000001
) то же самое, что"1" = 49 (dec) = 0x31 = 0b00110001
при использовании с%2
. - Избавьтесь от
delay(2000)
. Задержки — зло* :) Вы можете записывать значения на контакты целый день, и это не вызовет никаких проблем. Если вы хотите выводить меньше данных на последовательный порт (что вам и следует делать), вы можете сделать синхронизированный вывод обратно на последовательный порт. Например, выполняйтеSerial.println()
раз в секунду или записывайте значения в резервные/старые переменные и сравнивайте их, а вывод выводите только в случае изменения значения. - Самое важное — в следующем разделе
Короткая версия
Вот ваша главная проблема, в этой строке:
digitalWrite(lights[i+11], (binaryNumber[i] == '0' ? LOW : HIGH));
Я думаю, вам нужно:
digitalWrite(lights[i], (binaryNumber[i] == '0' ? LOW : HIGH));
У вас уже есть значение PIN-кода, закодированное в массиве, вам не нужно добавлять 11 к индексу, это поднимет вас выше трех значений света :)
* Задержки — зло: Это вопрос мнения, и это просто то, что я чувствую, я на самом деле погуглил, и это просто случайный ответ. Но он содержит суть того, что я бы сказал в любом случае: http://www.makeuseof.com/tag/arduino-delay-function-shouldnt-use/
Перед чтением необходимо проверить наличие доступных символов. См. документацию по Serial.read() (и Serial.available()).
Ура!
Глядя на вашу фотографию, кажется, что есть только одно соединение с каждым светодиодом. Вам также нужно заземление. У вас есть провод, который идет к шине заземления на плате прототипа, но не оттуда к самим светодиодам.
Я подключил резисторы между светодиодами и шиной заземления., @Jamerack
- Светодиоды: разница между общим анодом и общим катодом
- Акцептант векселей ИКТ
- if/else в digitalRead не выполняется в части else
- DHT11 не работает со светодиодом в arduino
- я не могу работать над своим небольшим проектом
- Вопрос об ошибке в этом коде
- Кастомная функция переключения светодиодов: один из трех светодиодов работает неправильно
- Как использовать SPI на Arduino?
Я собирался переписать ваш код, но вы в любом случае дали ему довольно хороший удар, так что возьмите мою информацию выше на вооружение и попробуйте еще раз. Если у вас возникнут какие-либо проблемы, опубликуйте свой новый код в обновлении вопроса, и мы поможем вам поработать над ним дальше. Если вы под кайфом и просто хотите получить ответ, дайте нам знать, и я или кто-то другой сможет подсказать вам, как мы это сделаем, но нет ничего лучше, чем учиться, чем делать это самостоятельно. Это засядет у вас в голове гораздо лучше, когда вы попробуете еще раз самостоятельно. Вы больше не будете делать ошибок, подобных этому
index
(или, во всяком случае, не таким образом), @MadivadСпасибо! На самом деле изначально у меня не было ошибки в индексе, но когда я вчера вечером просматривал ее, мой уставший разум подумал, что я допустил ошибку там, где ее не было, и исправил ее., @Jamerack
Удивительно, что иногда делает уставший разум. Я часто обнаруживаю, что пытаюсь закончить «одно дело» перед тем, как лечь спать, и это может поставить меня в тупик на несколько часов! В какой-то момент я сдаюсь и прекращаю работу. На следующее утро, отдохнувший, вы бросаете взгляд на него и видите то, что вы просто не можете поверить, что пропустили прошлой ночью, и за 30 секунд вы исправили предыдущие 4+ часа беспокойства. Вы думаете про себя, в следующий раз, когда это произойдет, я просто пойду спать. Но в следующий раз, когда это происходит, вы проводите еще одну ночь над одной проблемой, на решение которой уходит еще 30 секунд на следующий день, снова! lol, @Madivad
Я обязательно так и сделаю в следующий раз и избавлю себя от лишних хлопот, лол., @Jamerack