7

I'd like to 'clean up' some code that involves several pinMode() and digitalWrite() lines by using a single line of an array. I'm very new to both arrays so I'm a bit confused. The following examples are sections from code that controls a 4 digit, 7 segment LED.

// Define display pins
// Digit pins (common cathode)
int digit1 = 13; //Display pin 1
int digit2 = 12; //Display pin 2
int digit3 = 11; //Display pin 6
int digit4 = 10; //Display pin 8
// Segment pins
int segA = 2; //Display pin 14
int segB = 3; //Display pin 16
int segC = 4; //Display pin 13
int segD = 5; //Display pin 3
int segE = 6; //Display pin 5
int segF = 7; //Display pin 11
int segG = 8; //Display pin 15

void setup() {                
  pinMode(segA, OUTPUT);
  pinMode(segB, OUTPUT);
  pinMode(segC, OUTPUT);
  pinMode(segD, OUTPUT);
  pinMode(segE, OUTPUT);
  pinMode(segF, OUTPUT);
  pinMode(segG, OUTPUT);

  pinMode(digit1, OUTPUT);
  pinMode(digit2, OUTPUT);
  pinMode(digit3, OUTPUT);
  pinMode(digit4, OUTPUT);
}

#define SEGMENT_ON  LOW
#define SEGMENT_OFF HIGH

  switch (numberToDisplay){

  case 0:
    digitalWrite(segA, SEGMENT_ON);
    digitalWrite(segB, SEGMENT_ON);
    digitalWrite(segC, SEGMENT_ON);
    digitalWrite(segD, SEGMENT_ON);
    digitalWrite(segE, SEGMENT_ON);
    digitalWrite(segF, SEGMENT_ON);
    digitalWrite(segG, SEGMENT_OFF);
    break;

Defining pins:

I'm pretty sure the code below is the correct way to store the pins as an array (but please correct me if I'm wrong).

digitPins[] = {13 12 11 10};
segPins[] = {2 3 4 5 6 7 8};

pinMode():

I understand I could use a for loop to set the pin modes but is there an even simpler way? Would something like this work?

pinMode(digitPins[], OUTPUT);
pinMode(segPins[], OUTPUT);

digitalWrite():

I could access the appropriate pin from the array to use in digitalWrite() like the code below but that would result in the same number of lines of code (and be even more confusing). Is there another option?

digitalWrite(segPins[1], HIGH);
7

the correct way to store the pins as an array

Your array initializers are almost right; you just need to separate the values with commas:

digitPins[] = {13, 12, 11, 10};
segPins[] = {2, 3, 4, 5, 6, 7, 8};

You will need to call pinMode() in a loop; it doesn't accept arrays as arguments.

How about for digitalWrite() where its a mix of HIGH and LOW?

There are (at least) two ways: Make arrays of HIGH and LOW values, matching the digitPins[] and segPins[] arrays one-for-one, respectively. Or for easier maintenance, declare a data structure (struct) of a pin # and a value; make an array of those. It's a bit more complex but also more useful. So, for example:

typedef struct {
    uint8_t pinNum;
    bool pinVal;
} pinInit_t;

pinInit_t digitPins[] {
    {13, HIGH},
    {12, LOW},
    {11, LOW},
    {10, HIGH}
};

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

void loop() {
  // put your main code here, to run repeatedly:
}

struct is short for "data structure"; it lets you combine data of different types into a single named and addressable unit. typedef declares a new data type, and says "Don't allocate any memory just now; this (pinInit) is just a description. I'll use it later on." It makes pinInit a named data type, usable wherever you can use a native data type AND a multi-valued data type (such as an array) is permissible.

Thus, we can make an array of pinInits (pin-# / boolean-value pairs) just by using the name of the new type.

Then your initializing code might look like:

uint8_t i;
for( i = 0; i < sizeof(digitPins)/sizeof(pinInit_t); ++i ){
   pinMode(digitPins[i].pinNum, OUTPUT);
   digitalWrite(digitPins[i].pinNum, digitPins[i].pinVal);
}

The expression sizeof(digitPins)/sizeof(pinInit) evaluates to the number of initializers (# of bytes in the array / # of bytes in one array member).

The expression digitPins[i].pinNum means: "in the pinInit array digitPins, get the i-th element..." (remember, this is a pair of values), "... and take value of the member "pinNum". A little more complex, the first time we think about it, but look at how easily the array reads. And a hint about reading that expression: I read it backwards: "the pinNum member of the i-th element of the digitPins array."

Tomorrow, or next month, when we need another pin, no need to update 2 arrays (remembering of course, to keep them in sequence with each other!); just add another 2-valued element to the one digitPins[] array.

|improve this answer|||||
3

[ADDITIONNAL CODE and EXPLANATION OF THE CODE]

This is the function that is used in the link posted in the comments:

void number(int num)                        //num is the number to display
{
  for(int i=0; i<7; i++)                    //going through the 7-segments (7 leds)
  {
    digitalWrite(segment[i], nums[num][i]); //tell the arduino to turn on or off which led
  }
}

It is great because you can use it by calling:

number(/*the number you want to display*/);

Using a for loop will avoid copying and pasting a buch of things. It also permits you do save a lot of memory.

Then, to display a small 0-9 timer, you can do this:

for(int i=0; i<10; i++)
{
  number(i);            //display the number
  delay(1000);          //wait 1sec
}

[ORIGINAL ANWSER]

Use an array and a for loop.

int segments = {2,3,4,5,6,7,8}; //declaring the pins

void setup() {
  for(int i=0;i<8;i++)
  {
    pinMode(segments[i], OUTPUT); //declaring them as outputs
  }
}

It's very useful. Do the same for the digits too.

This method works in many cases:

  • many sensors, switches
  • many outputs such as leds, relays, transistors
|improve this answer|||||
  • 1
    How about for digitalWrite() where its a mix of HIGH and LOW? – zdub Oct 19 '16 at 16:28
  • @zdub that will indeed make things more complicated, but if you want a good solution to what you are likely looking for, you should edit your question to show more than one possibility for the data to be written. – Chris Stratton Oct 19 '16 at 16:30
  • here is a post I posted quite a while ago about 7-seg: arduino.stackexchange.com/questions/30031/… – Dat Ha Oct 19 '16 at 16:32
  • 1
    For a mix of HIGH and LOW just have the list of HIGH and LOW in an array as well. By the way, be sure to make the array const and, even better, arrange it in PROGMEM as well, though that has performance implications. – Majenko Oct 19 '16 at 17:34
  • @canadiancyborg 2D arrays!! Didn't know this was an option but I think it will work. Why does this digitalWrite(segment[i], nums[num][i]) have to be in a for loop? Why cant 'i' just be a variable and the code works without the for loop. – zdub Oct 19 '16 at 19:02
0

Custom method usage

Used reference: https://stackoverflow.com/a/33235154/5500092

You can use a custom method like this:

template<size_t size>
void pinMode(const uint8_t (&pin)[size], uint8_t mode) {
    for (size_t i = 0; i < size; ++i) {
        pinMode(pin[i], mode);
    }
}

template<size_t size>
void digitalWrite(const uint8_t (&pin)[size], uint8_t val) {
    for (size_t i = 0; i < size; ++i) {
        digitalWrite(pin[i], val);
    }
}

Then you define an array with the pins:

uint8_t displayPins[4] = {13, 12, 11, 10};
uint8_t segmentPins[7] = {2, 3, 4, 5, 6, 7, 8};

And finally in your setup use:

void setup() {                
    pinMode(displayPins, OUTPUT);
    pinMode(segmentPins, OUTPUT);
}

void loop() {
    // Your logic with digitalWrite.
}

Your logic

PS: For your logic, you can even use:

template<size_t size>
void digitalWrite(const uint8_t (&pin)[size], const uint8_t (&val)[size]) {
    for (size_t i = 0; i < size; ++i) {
        digitalWrite(pin[i], val[i]);
    }
}

And define for each segment number a custom value array.

uint8_t zero[7] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW};
...

Or even:

uint8_t segment[][7] = {{HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW }, // 0
                        {____, ____, ____, ____, ____, ____, ____}, // 1
                        {____, ____, ____, ____, ____, ____, ____}, // 2
                        ...
                        {____, ____, ____, ____, ____, ____, ____}}; // F

And use:

digitalWrite(segmentPins, segment[5]); // print 5
|improve this answer|||||
-4
func(){ 
   boolean pins[] ={ 1,1,1,1,1,1,0};
   for(int i=0; i<7;i++)`
   digitalWrite(segPins[i], pins[i]);
}

thats all :)

|improve this answer|||||
  • Please add a text description why your proposed solution is the answer. Also correctly format your code. Please read How to I write a good answer. If you give a well presented answer you will not get so many downvotes. – Greenonline Jul 4 '18 at 15:54
  • 1. That doesn't help, as you would need one such function for each of the ten digits. 2. It doesn't compile. – Edgar Bonet Jul 4 '18 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.