Pointing to / Copying an Array

Hey guys,

So i have a project where i am presenting data sets on displays. My current setup is that i have 2 arduinos and 13 displays over I2C (7 to one and 6 to another).

As you can see from my code below i want to be able to swap from 1 data array to another via a button press, this button press must hold its state. ie. when i press the button, the display shows just data array 1 until it is pressed again where it displays data 2 and so on.

My question then, what is the best way to have this button press swap arrays?

My first thought was just create another array and “copy” in the elements from the data array based up an “if” statement (it doesn’t work, who’d have guessed). A colleague (im doing a work placement for the summer) said to me to look into pointers, which i have, but all i can find are examples like: x=2, y*=x etc which i can not seem to translate to help me.

Any sources of information or nudges in the right direction would be gratefully received!

thanks a mill

#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
  
Adafruit_7segment segment[6];

int address[6]={112,113,114,115,116,117};        // display addresses

int data2[10][6] =
{
  {101,102,103,104,105,106},
  {107,108,109,110,111,112},
  {113,114,115,116,117,118},
  {119,120,121,122,123,124},
  {125,126,127,128,129,130},                   //data set 2
  {131,132,133,134,135,136},
  {137,138,139,140,141,142},                  // arbitrary numbers currently
  {143,144,145,146,147,148},
  {149,150,151,152,153,154},
  {155,156,157,158,159,160}
};

int data1[10][6] =
{
  {1,2,3,4,5,6},
  {7,8,9,10,11,12},
  {13,14,15,16,17,18},
  {19,20,21,22,23,24},
  {25,26,27,28,29,30},
  {31,32,33,34,35,36},                      //data set 1
  {37,38,39,40,41,42},
  {43,44,45,46,47,48},
  {49,50,51,52,53,54},
  {55,56,57,58,59,60}
};

int interruptFlag = 0;
const int interruptPin = 2;
const int button = 12;
int buttonState;
int dataSet[10][6];
int lastButtonState = LOW;                         // button setup with debounce (i hope!)
int reading = digitalRead(button);
long lastDebounceTime = 0;
long debounceDelay = 50;

void Pins ()
{
  pinMode(12,INPUT);
  pinMode(8,OUTPUT);
  pinMode(7,OUTPUT);           // 2 outputs so i can control both arduinos based upon timingControl()
  digitalWrite(8,HIGH);
  digitalWrite(7,HIGH);
}

void timingControl ()
{
  digitalWrite(8,LOW);
  digitalWrite(7,LOW);
  delay(1000);                           // this delay controls how quickly the displays cycle through the arrays
  digitalWrite(8,HIGH);
  digitalWrite(7,HIGH);
}

void buttonPress()
{
  if (reading != lastButtonState)
  {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay)       // this i hope is a debounce for my button
  {
    if (reading != buttonState)
    {
      buttonState = reading;
    }
    if (buttonState == HIGH)
    {
      dataSet[10][6] = data1[10][6];           // here is my issue with how to "copy" an array
    } 
    else
    {
      dataSet[10][6] = data2[10][6];
    }
  }
  lastButtonState = reading;
}

void interrupt_ISR() 
{ 
  interruptFlag = 1;               // an interrupt to allow the pins 7 and 8 to control the displays
} 

void setup() 
{
  #ifndef __AVR_ATtiny85__
  Serial.begin(9600);
  #endif

  for (int i=0;i<6;i++) 
  {
    segment[i]=Adafruit_7segment();
    segment[i].setBrightness(10);
    segment[i].begin(address[i]);                      
  }
  
  Pins();
  attachInterrupt(0, interrupt_ISR, CHANGE);
  digitalWrite(interruptPin,HIGH);
}

void loop()
{
  for (int k=0; k<10; k++)
  {
    timingControl();
    if (interruptFlag == 1) 
    {
      for (int i=0; i<6; i++)
      {
        buttonPress();
        segment[i].print(dataSet[k][i]);
        segment[i].writeDisplay();
        delay(10);
      }
    }  
    else
    {
      while (interruptFlag != 1) 
      {
        if (digitalRead(8) == HIGH) 
        {
          interruptFlag = 1;
        }
        else {;}
      }  
    }
    interruptFlag = 0;
  }   
}
dataSet[10][6] = data2[10][6];

That just instructs the compiler to find data at position 10,6 in your data2 array and copy it in position 10,6 of dataSet. This does not copy the full array and this will overflow because index in the arrays are from 0 to 9 and 0 to 5

The easiest way would be to just declare your data as an array of 60 int, not 2 dimensional (so don't use the multiple {} per line, just dump everything in there)

int data1[] = {
1,2,3,4,5,6,
7,8,9,10,11,12,
...
55,56,57,58,59,60
}

Or just int data1[60];if that array will be initialized with content later

and change wherever you were accessing data like thissegment[i].print(dataSet[k][i]);Into segment[i].print(dataSet[10*k+i]);

Declare dataSet and a pointer to int int * dataSet; and when you need to switch do dataSet = data1; // or dataSet=data2;

Further to what J-M-L said, you could toggle a flag when a valid button press is detected, then choose the data set according to the flag's state.

boolean bDataFlag = 0;  // 0 = data1, 1 = data2
.
.
if(buttonState == HIGH)
    bDataFlag ^=1;    // Toggle the flag

if(bDataFlag)
    dataSet = data2;
else
    dataSet = data1;

thank you for your responses.

Looking through what both of you have said, although it would work is there a way to use that flagging system that Steve has mentioned without changing my arrays and pieces of code associated?

The reason they are 2 dimensional arrays (and must stay that way) is due to the data that will eventually be put into there. I'm ending up with thousands of numbers which are in that format. Easier to code for that than change the data set to fit my code.

J-M-L:
Declare dataSet and a pointer to int int * dataSet; and when you need to switch do dataSet = data1; // or dataSet=data2;

This is exactly what i need but for a 2 dimensional array, I'm not well versed in coding and especially not pointers, is it possible?

Sur you could set the flag on which dataSet to use when button is Pressed and then wherever you touch the array you do

IF dataSetFlag == 1 then use data1 else use data2

Means you need to do that everywhere.

I have not tested this but this is likely to work (need to verify how the int array data is layered in memory) - if you want to keep the 2d array and not perform the math to end up at the right index then dataSet needs to be an array of ten pointers to arrays of 6 int. So you would declare

int * dataSet[10]; // ten pointers to integers

And when you need to switch you would need a for loop from 0 to 9 allocating the 10 right addresses in memory

dataSet[0] would be &(data1[0][0]); // or data2 depending which one you want to point at
dataSet[1] would be &(data1[1][0]);
...
dataSet[9] would be &(data1[9][0]);

So something like

for (int i=0;i<10;i++) dataSet[i] = &(data1[i][0]); // or data2 similarily

Then you can do dataSet[x][y]as you would do with data1[x][y] // or data2[x][y]

J-M-L:
Sur you could set the flag on which dataSet to use when button is Pressed and then wherever you touch the array you do

IF dataSetFlag == 1 then use data1 else use data2

Means you need to do that everywhere.

It only needs doing immediately after the button press, to point to one or the other of the data arrays. (Using two individual arrays as you suggested, rather than 2-dimensional arrays.)
It doesn't need to be done anywhere else. A pointer to one or the other of the data sets will be stored each time a valid button press is detected.

ciaranq wrote (in part):

I’m ending up with thousands of numbers which are in that format.

I hope that you are using an Arduino with sufficient memory.

OldSteve:
It only needs doing immediately after the button press, to point to one or the other of the data arrays. (Using two individual arrays as you suggested, rather than 2-dimensional arrays.)
It doesn't need to be done anywhere else. A pointer to one or the other of the data sets will be stored each time a valid button press is detected.

What I meant is that if he does not want to use the pointer then he can use the Boolean to decide which data1/data2 to use everywhere else in the code

J-M-L:
What I meant is that if he does not want to use the pointer then he can use the Boolean to decide which data1/data2 to use everywhere else in the code

Ah right. Now I follow. I misunderstood. :slight_smile:

The reason they are 2 dimensional arrays (and must stay that way) is due to the data that will eventually be put into there. I'm ending up with thousands of numbers which are in that format. Easier to code for that than change the data set to fit my code.

You understand that memory is just linear, right? So a 2d array is just a 1d array - integers are next to one another in memory and when you do data1[k][i]) the compiler knows the size of the first dimension and calculates where to jump in memory and goes fetching/setting data1[10*k+i].

I don't think it's is much more difficult to spell out the 10*k+i than having the 2 brackets but that's your choice