Binary Counter LED Project Issue

Hello all. I am very new to hobbyist electronics and fairly new to programming. I have the Uno starter kit from Elegoo and have been working through the Paul McWhorter Arduino playlist on YouTube. I just finished the binary numbers video, and the assignment he gave is to wire up 4 LEDs (this part is done and working correctly), and then to write a program that will count from 0-15 in binary using said LEDs. My approach with this Arduino course is to figure out these projects before moving to the next video. The sketch I created is what I thought would work most efficiently and dynamically (in case I want to make changes), instead of just a bunch of copy-pasted lines of digital writes and then delays.

The issue I'm having is, when I upload to the board or press the button to restart, all 4 LEDs light up and stay lit indefinitely. I have almost no C++ experience, so perhaps I'm not using proper syntax or not using the arrays correctly. I will paste my code below, and I'm sure many of you will very quickly see what I'm doing wrong. Also, I'm very sorry if any formatting looks off, specifically indentation. If it is please let me know because I am very open to criticism and learning.

On a side note, I would like to accelerate my learning timeline when it comes to C++. I love Paul's videos so far, but I do not want to solely rely on them for the coding aspect so that I can be more confident in my solutions for these course projects. Is learncpp.com a resource that you would recommend?

int loopCounter = 0;
int loopDelay = 1500;
int writeValueLed1 = "LOW";
int writeValueLed2 = "LOW";
int writeValueLed3 = "LOW";
int writeValueLed4 = "LOW";
int ledPin1 = 10;
int ledPin2 = 11;
int ledPin3 = 12;
int ledPin4 = 13;
int numArray1[8] = {0,2,4,6,8,10,12,14};
int numArray2[8] = {0,1,4,5,8,9,12,13};
int numArray3[8] = {0,1,2,3,8,9,10,11};
int numArray4[8] = {0,1,2,3,4,5,6,7};
bool match1 = false;

void setup() {
  // put your setup code here, to run once:

pinMode(ledPin1,OUTPUT);

pinMode(ledPin2,OUTPUT);

pinMode(ledPin3,OUTPUT);

pinMode(ledPin4,OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  
  for(int i = 0; i < 8; i++) {
    if(numArray1[i] == loopCounter) {
      match1 = true;
      break;
   }
  }

  if(match1) {

    writeValueLed1 = "LOW";

  }
  
  else {

    writeValueLed1 = "HIGH";

  }

  match1 = false;
  for(int i = 0; i < 8; i++) {
    if(numArray2[i] == loopCounter) {
      match1 = true;
      break;
   }
  }

  if(loopCounter == numArray2) {

    writeValueLed2 = "LOW";

  }
  
  else {

    writeValueLed2 = "HIGH";

  }

  match1 = false;
  for(int i = 0; i < 8; i++) {
    if(numArray3[i] == loopCounter) {
      match1 = true;
      break;
    }
  }

  if(loopCounter == numArray3) {

    writeValueLed3 = "LOW";

  }
  
  else {

    writeValueLed3 = "HIGH";

  }

  match1 = false;
  for(int i = 0; i < 8; i++) {
    if(numArray4[i] == loopCounter) {
      match1 = true;
      break;
    }
  }

  if(loopCounter == numArray4) {

    writeValueLed4 = "LOW";

  }
  
  else {

    writeValueLed4 = "HIGH";

  }
match1 = false;
digitalWrite(ledPin1,writeValueLed1);
digitalWrite(ledPin2,writeValueLed2);
digitalWrite(ledPin3,writeValueLed3);
digitalWrite(ledPin4,writeValueLed4);

delay(loopDelay);

  if(loopCounter == 15) {
    loopCounter = 0;
  }

  else {
    loopCounter = loopCounter + 1;
  }


}

Welcome to the forum

I started to look at your code and saw

int writeValueLed1 = "LOW";

An int holds a single integer value. It cannot hold a string of characters

I stopped looking at the code at that point

You need to learn basic C before undertaking any project

2 Likes

Oh dear; Arduino's "let's not show many/any warnings by default" bites another user.

Here's the result of compiling your sketch as is with all compiler warnings turned on.

arduino-cli compile -b arduino:avr:uno --warnings all --output-dir ~/tmp --no-color (in directory: /home/me/Documents/sketchbook/Uno_R3/test)
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:3:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
 int writeValueLed1 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:4:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
 int writeValueLed2 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:5:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
 int writeValueLed3 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:6:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
 int writeValueLed4 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino: In function 'void loop()':
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:42:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed1 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:48:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed1 = "HIGH";
                      ^~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:60:21: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
   if(loopCounter == numArray2) {
                     ^~~~~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:62:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed2 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:68:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed2 = "HIGH";
                      ^~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:80:21: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
   if(loopCounter == numArray3) {
                     ^~~~~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:82:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed3 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:88:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed3 = "HIGH";
                      ^~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:100:21: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
   if(loopCounter == numArray4) {
                     ^~~~~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:102:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed4 = "LOW";
                      ^~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:108:22: warning: invalid conversion from 'const char*' to 'int' [-fpermissive]
     writeValueLed4 = "HIGH";
                      ^~~~~~
Sketch uses 4192 bytes (12%) of program storage space. Maximum is 32256 bytes.
Global variables use 94 bytes (4%) of dynamic memory, leaving 1954 bytes for local variables. Maximum is 2048 bytes.
Compilation finished successfully.

As you can see, assigning character string literals to integer variables doesn't do what you think it does.

1 Like

How far into C should I get before hopping back into C++? What subject would be a good stopping point? I would be fine with returning to C in the future. Unless if it's often recommended to go the whole way with C before touching anything else.

What an embarrassing mistake. I'm guessing the fix is not as simple as just declaring the writeValueLed variables as string instead of int.

No. It's simpler! :slightly_smiling_face: Replace "LOW" with LOW and "HIGH" with HIGH. That gets you down to 3 warnings.

arduino-cli compile -b arduino:avr:uno --warnings all --output-dir ~/tmp --no-color (in directory: /home/me/Documents/sketchbook/Uno_R3/test)
/home/me/Documents/sketchbook/Uno_R3/test/test.ino: In function 'void loop()':
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:60:21: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
   if(loopCounter == numArray2) {
                     ^~~~~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:80:21: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
   if(loopCounter == numArray3) {
                     ^~~~~~~~~
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:100:21: warning: ISO C++ forbids comparison between pointer and integer [-fpermissive]
   if(loopCounter == numArray4) {
                     ^~~~~~~~~
Sketch uses 4170 bytes (12%) of program storage space. Maximum is 32256 bytes.
Global variables use 84 bytes (4%) of dynamic memory, leaving 1964 bytes for local variables. Maximum is 2048 bytes.
Compilation finished successfully.

But what @UKHeliBob said in post #2 holds: you really need to learn basic C first. I heartily recommend digging up a copy of "Arduino For Dummies". I've used books in that series many many times over the years.

1 Like

My advice at your stage would be to ignore the difference between C and C++ and jump straight into C++. The Arduino IDE uses C++ with extensions for the control of peripherals

Start by looking at and trying the examples in the IDE. The IDE has a link to the Arduino Language Reference which you should find helpful. Note that it is not a complete C/C++ reference but does include some C/C++ contents

When you find code in the IDE examples that you do not understand look in the reference and if it is of no help use Google. Don't forget that you can also search the forum

1 Like

The C Programming Language provide many small programs demonstrating the language and how it can be used.

1 Like

Expanding on what has been said so far and providing some information that you might find useful with the current experiment.

You correctly put your pins into OUTPUT mode


pinMode(ledPin1,OUTPUT);

pinMode(ledPin2,OUTPUT);

pinMode(ledPin3,OUTPUT);

pinMode(ledPin4,OUTPUT);

But you went astray when you wanted to write their on off values. There are two options

Using HIGH

digitalWrite(ledPin1,HIGH);

or what might be better for manipulating on off values you could use 1 or 0


// set output off, in this case I used the data type byte 
byte writeValueLed1 = 0;

digitalWrite(ledPin1,writeValueLed1);


// set output on
writeValueLed1 = 1;

digitalWrite(ledPin1,writeValueLed1);

This gives an advantage of controlling all 4 pins just using 1 number, for example make the number 15 and it gives a binary value of 00001111 which would be the value to turn all 4 leds on. Research the Arduino instruction bitRead(x,n) on how to read whether a bit is high or low

1 Like

I see no string

Yes my mistake , HIGH equates to 1

You might be interested in getting an example of Michael Margolis Arduino Cookbook...

It is a great companion to learning C++.

The book provides a comprehensive introduction to the use of Arduino boards and consists of nicely structured projects.

Studying the different solutions will provide you a sound basis for your own developments. It does not replace a good C++ book but combines the basic knowledge regarding the programming language and the use of the different hardware components involved.

Good luck!

2 Likes

This seems like a great resource! Thank you

Thank you for pointing me in the right direction without spoiling the whole solution for me! Haha I appreciate your help. I will take your and @UKHeliBob 's advice by starting to dive into learning the language. I'll take a look at your book recommendation (thanks for that as well).

I went into settings and turned on all warnings so that I could get the ones you pasted here. I noticed only 3 out of the 4 if statements were spitting out errors. So I went to the correct one and realized I forgot to replace the loopCounter == numArray condition with the match1 boolean in the other 3 if's. That, coupled with the advice in your other reply of removing the quotation marks in the declarations, got me all sorted! Thanks again!

I will paste the new code here now that it is working properly:

int loopCounter = 0;
int loopDelay = 1500;
int writeValueLed1 = LOW;
int writeValueLed2 = LOW;
int writeValueLed3 = LOW;
int writeValueLed4 = LOW;
int ledPin1 = 10;
int ledPin2 = 11;
int ledPin3 = 12;
int ledPin4 = 13;
int numArray1[8] = {0,2,4,6,8,10,12,14};
int numArray2[8] = {0,1,4,5,8,9,12,13};
int numArray3[8] = {0,1,2,3,8,9,10,11};
int numArray4[8] = {0,1,2,3,4,5,6,7};
bool match1 = false;

void setup() {
  // put your setup code here, to run once:

pinMode(ledPin1,OUTPUT);

pinMode(ledPin2,OUTPUT);

pinMode(ledPin3,OUTPUT);

pinMode(ledPin4,OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  
  for(int i = 0; i < 8; i++) {
    if(numArray1[i] == loopCounter) {
      match1 = true;
      break;
   }
  }

  if(match1) {

    writeValueLed1 = LOW;

  }
  
  else {

    writeValueLed1 = HIGH;

  }

  match1 = false;
  for(int i = 0; i < 8; i++) {
    if(numArray2[i] == loopCounter) {
      match1 = true;
      break;
   }
  }

  if(match1) {

    writeValueLed2 = LOW;

  }
  
  else {

    writeValueLed2 = HIGH;

  }

  match1 = false;
  for(int i = 0; i < 8; i++) {
    if(numArray3[i] == loopCounter) {
      match1 = true;
      break;
    }
  }

  if(match1) {

    writeValueLed3 = LOW;

  }
  
  else {

    writeValueLed3 = HIGH;

  }

  match1 = false;
  for(int i = 0; i < 8; i++) {
    if(numArray4[i] == loopCounter) {
      match1 = true;
      break;
    }
  }

  if(match1) {

    writeValueLed4 = LOW;

  }
  
  else {

    writeValueLed4 = HIGH;

  }
match1 = false;
digitalWrite(ledPin1,writeValueLed1);
digitalWrite(ledPin2,writeValueLed2);
digitalWrite(ledPin3,writeValueLed3);
digitalWrite(ledPin4,writeValueLed4);

delay(loopDelay);

  if(loopCounter == 15) {
    loopCounter = 0;
  }

  else {
    loopCounter = loopCounter + 1;
  }


}

(post deleted by author)

I have yet to write much C++ after some good long time getting along just fine with C.

Of course I use C++ inadvertently all the time. I probably used it before I realized I was doing.

Serial.println("hello, world.");   // I'm a C++ programmer now

I do use some C++ but minor things that are fun and convenient and fit well with my understanding of C.

Most of what makes C++ really fly will be harder to learn if you don't have C syntax practically living in your elbows, and haven't done a few and a few more projects fully exploiting C language features.

C is a good match to microprocessors. It is a relatively tiny language: modern languages that have roots in C usually cover all of what C brings to the table in the first few chapters.

I'd say don't even worry about C++. It could turn into not ever worrying about it.

I'd say it's harder to learn how to program and learn C++ at the same time than it is to learn how to program and learn C at the same time. And nothing you know or learn about C will be so wrong or so out of date or otherwise worthkess that doing would have been a waste of time.

+1. The Bible as some refer to it is not aimed at the kind of coding you will do on these small machines, but it is an excellent exposition of the language and its once unique and revolutionary philosophy.

I'd say just lesrn the basics of C, except C is so tiny that the basics are really the entirety of the language.

When your coding efforts stall because multidimensional arrays of structs just aren't cutting it, turn to C++. I can't say it will fix you right up, but it wouldn't be the curveball it might seem like it is today.

a7

2 Likes

We had fun tinkering with your sketch until it worked. We added a crapton of printing to see it work its way to the conclusion which is turning on the correct LEDs.

Your core logic and structure were fine as you see, the algorithm and supporting dtat structures were correct.

Now to accelerate your learning here is a goal: use arrays to cut down the repetition in your code.

Whenever you make variables by appending a differentiating number or letter, it is time to wonder if an array would be suitable.

And when you grow code by copy/paste/editing, it is time to think about loops and functions.

And here's where you'll need a two dimensional array… once you see how easy it is you'll wonder why it was ever hard.

The manner of counting in binary you present is a nice literal machine, charming. It would scale nicely; at some point you'd want to write a program whose output would be the two dimensional numArray initial values.

So I assume the point was the algorithm itself. It presents nice opportunities for stepwise improvements. If the code was generalized, improving it would mean changing the code in only one place, not N number of bits (4) copies.

a7

1 Like

If I have a program which I can complete using C only, then should I still use C++?

"should", no.

i suggest you learn to write well organzied programs and avoid the tediousness of using classes. But it's hard to do this on your own, it's better to see well written programs (how do you know which are well written? The authors of The Elements of Programming Style dissected poorly written textbook examples).

Brian Kernighan said C++ has "guard rails" that C doesn't have for large programs. But bear in mind that C was used to write UNIX and Linux and Arduino programs are tiny.

object oriented code groups variables and functions for well defined purpose. They could just be a part of a larger file, or in a separate file or in a class.

1 Like

Your proposition goes inline with Brian Kernighan's