sábado, 7 de abril de 2012

Matrizes Multi-Dimensionais no Arduino

Em uma aula do Curso Arduino aprendemos sobre matrizes de 1 dimensão, ou seja, matrizes com um indíce. Não existe nada que diga que matrizes são limitadas a uma única dimensão de vetores. Na verdade, você pode ter um número arbitrário de dimensões em uma matriz. As matrizes de 2 dimensões são muito comuns, especialmente para guardar coisas como coordenadas de uma tela, ou linhas e colunas de uma planilha. Dimensões maiores são usadas quando temos mais aspectos que especificam mais itens únicos (coordenadas 3D, por exemplo).
Uma coisa importante a se entender sobre matrizes é que tecnicamente, não existe tal coisa como matriz multi-dimensional. Todas camadas são vetores (ou matrizes de uma dimensão), mas algumas delas contém matrizes de matrizes de matrizes. Isso significa que quando você encontra algo como isso:
int multiarray[4][2]


Você provavelmente está pensando em uma grade de inteiros como isso:
   0       1
0 [0][0]  [0][1]
1 [1][0]  [1][1]
2 [2][0]  [2][1]
3 [3][0]  [3][1]


Na realidade, o Arduino não pode guardar a “grade”, pois a memória é uma longa linha de endereços. A linguagem C trata cada linha como uma matriz de 2 elementos, a qual é um único elemento de 4 matrizes de elementos. Em outras palavras, cada elemento é uma matriz, que contém 2 elementos. Então a variável multiarray[0] é uma matriz de 2 elementos, multiarray[1] é outra matriz de 2 elementos, assim por diante. Isso também significa que multiarray[0] é um ponteiro! O tipo da variável multiarray[0] é int*. Assim, como a variável multiarray é um ponteiro para multiarray[0], isso significa que o tipo dela é int(*)[2]!!!
Se você pensa que está ficando confuso, você está certo! Se você acha que existe muita probabilidade de um código baseado em matrizes não funcionar, acertou de novo! Vamos adicionar mais um pouco de confusão aqui. Eu disse que a matriz não pode ser armazenada como uma grade, vamos dar uma olhada como ela é guardada.

A variável multiarray tem 4 elementos, então deve se parecer com isso:
|  conteúdo em 0 || conteúdo em 1 || conteúdo em 2 || conteúdo em 3 |
   multiarray[0]    multiarray[1]   multiarray[2]     multiarray[3]

Como cada elemento de multiarray é uma matriz de 2 inteiros, que significa que “conteúdo em” são 2 inteiros consecutivos, assim:
memória:    |[int0] [int1]||[int0] [int1]||[int0] [int1]||[int0] [int1]|
multiarray:       [0]            [1]            [2]            [3]
multiarray:  [0][0] [0][1]  [1][0] [1][1]  [2][0] [2][1]  [3][0] [3][1] 

Isso significa que você pode lidar de duas formas, como 4 matrizes de 2 elementos, ou uma matriz simples de 8 elementos.

Vamos ver como utilizar as duas formas de acessar matrizes, utilizando funções.
void setup()
{
   Serial.begin(9600);
}
void setarray(int ma[][2],int size)
{
  for (int i=0;i<size;i++)
    for (int j=0;j<2;j++)
      ma[i][j] = 10*i+j;
}
void printarray(int* ma,int dim1, int dim2)
{
  for (int i=0;i<dim1;i++)
  {
    for (int j=0;j<dim2;j++) {
      Serial.print(*(ma+(i*dim2+j)));
 Serial.print(" ");
     }
    Serial.println(" ");
  }
}
void loop()
{
  int multiarray[4][2];
  setarray(multiarray,4);
  printarray(&multiarray[0][0],4,2);
   while(true); // fica parado
}


Na função setarray(), o tamanho da sub-matriz é fixa, ficando mais fácil de utilizar. O problema é que não é flexivel. Em contrapartida, printarray() é muito mais complicado de implementar, mas muito mais flexível também. Repare que printarray simplesmente pega o endereço do primeiro elemento e o explora de forma linear, da mesma forma que é armazenado na memória. Ao utilizar o código acima, temos o seguinte resultado:
0 1 
10 11 
20 21 
30 31 

Não é necessário dizer que matrizes de 3, 4 ou mais dimensões aumentam muito a complexidade quando utilizadas em parâmetros de funções. 

3 comentários:

  1. Muito bacana,pirei legal na explicação,mas entendi a lógica,tava procurando uma forma de gerar barras no lcd 16x2 de acordo com o valor de um sensor,e também escrever mensagens pre definidas de conforme o valor encontrado em uma matriz mas isso me foi útil,vwm

    Murilo M. Ag.

    ResponderExcluir
  2. Obrigado pelo comentário!!!
    Participe do forum do curso Arduino, poste suas duvidas tecnicas la!!!
    Existem tópicos exclusivos separados por aula.
    http://www.youtube.com/user/graccula?feature=guide
    Abraços
    Renato

    ResponderExcluir
  3. Renato bom dia,
    Estou tendo dificuldades para solucionar uma questão onde desejo utilizar vetores, gostaria de saber se pode me ajudar?
    A questão é a seguinte:
    Quero montar uma matriz com as colunas dias da semana e nas linhas S1, S2,S3,S4. Em cada uma das posições armazenar, por exemplo, se segunda feira S1 estará ativo, mais tarde ler essas informações e executar as tarefas. Como no exemplo abaixo: onde a letra do dia significa ativo e o "_" significa inativo.

    S T Q Q S S
    S1 _ _ _ _ _ _ _
    S2 _ T _ Q S _ D
    S3 S T Q _ S S _
    S4 S _ Q Q S S _

    Esses dados serão configurados por um menu com display e botões.

    ResponderExcluir