Dopo il post precedente (Arduino & Registro SIPO) ho deciso di realizzare una piccola matrice di LED dalle dimensioni 4 x 4 controllate da due registri a scorrimenti 74164 (datasheet).

Inizialmente avevo sviluppato il programma solo per fare dei semplici giochi di luce ma successivamente ho deciso di aggiungere al progetto il Nunchuck in modo da poter muovermi punto per punto sulla matrice e selezionare un punto ed accenderlo!

Mi spiego meglio: alimentando il circuito inizierà a lampeggiare un punto sulla matrice, questo punto può essere spostato tramite il joystick del nunchuck e tramite il pulsante C posso “selezionare” quel punto e lasciarlo sempre acceso.

Premendo il pulsante Z invece i led si accendono tutti.

Video:

 

Ecco lo schema di collegamento:

I pin non collegati dei 74164 sono le uscite A-B-C-….H e vanno collegati tramite resistenza ai led.

I due integrati sono, come detto prima, registri a scorrimento (da 8bit) e sono collegati in cascata per cui l’uscita H del primo integrato va all’ingresso dati del secondo integrato.

I collegamenti ai led devono essere così impostati:

A B C D <- Primo 74164

E F G H <- Primo 74164

A B C D <- Secondo 74164

E F G H <- Secondo 74164

Consultare il datasheet per il pinout dell’integrato.

Ed ecco il codice sorgente:

/*Controllo di una matrice di led 4x4 tramite
 registri SIPO 74164. 

 Versione 2 - Aggiunto il nunchuck
 Xfox
 */

//Includo librerie
#include <Wire.h>
#include <string.h>
#undef int
#include <stdio.h>

const int datapin = 2; //Pin di serial
const int clockpin = 3; //Pin di clock
const int catodo = 5; //Catodo

byte primobyte = B00000000;
byte secondobyte = B00000000;

byte primo_point, secondo_point, terzo_point, quarto_point = B0000;
byte xpos = B1000;

long delaytime = 100;

//Variabili per i dati Nunchuck
int joy_x_axis = 0;
int joy_y_axis = 0;
int accel_x_axis = 0;
int accel_y_axis = 0;
int accel_z_axis = 0;
int z_button = 1;
int c_button = 1;
//Variabili Nunchuck
uint8_t outbuf[6];
int cnt = 0;

int posizione_x = 2;
int posizione_y = 2;

int griglia[5][5] = {
  {
    B0,B0,B0,B0,B0                } //Rga inutile ma necessaria per far si che gli arry partano da griglia [1][1]
  ,{
    B0,B0,B0,B0,B0            }
  ,{
    B0,B0,B0,B0,B0               }
  ,{
    B0,B0,B0,B0,B0              }
  ,
  {
    B0,B0,B0,B0,B0             }
};

void setup(){
Serial.begin(9600);

  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(catodo, OUTPUT);

  Wire.begin ();		// join i2c bus with address 0x52
  nunchuck_init (); // send the initilization handshake
}

void loop(){

  Nunchuck(); //Richiama funzione per acquisire dati nunchuck
  controlloxy();

  if (z_button == 0){
    scrivi(B1111, B1111, B1111, B1111, 0);
  }

  if(c_button == 0){
    set(posizione_x, posizione_y);
    delay(300);
  }

/*
  //Primo gioco
   point(1, 1);
   delay(delaytime);

   point(2, 1);
   delay(delaytime);

   point(3, 1);
   delay(delaytime);

   point(4, 1);
   delay(delaytime);

   point(4, 2);
   delay(delaytime);

   point(4, 3);
   delay(delaytime);

   point(4, 4);
   delay(delaytime);

   point(3, 4);
   delay(delaytime);

   point(2, 4);
   delay(delaytime);

   point(1, 4);
   delay(delaytime);

   point(1, 3);
   delay(delaytime);

   point(1, 2);
   delay(delaytime);

   //Secondo gioco
   point(1, 1);
   delay(delaytime);

   point(2, 1);
   delay(delaytime);

   point(3, 1);
   delay(delaytime);

   point(4, 1);
   delay(delaytime);

   point(4, 2);
   delay(delaytime);

   point(3, 2);
   delay(delaytime);

   point(2, 2);
   delay(delaytime);

   point(1, 2);
   delay(delaytime);

   point(1, 3);
   delay(delaytime);

   point(2, 3);
   delay(delaytime);

   point(3, 3);
   delay(delaytime);

   point(4, 3);
   delay(delaytime);

   point(4, 4);
   delay(delaytime);

   point(3, 4);
   delay(delaytime);

   point(2, 4);
   delay(delaytime);

   point(1, 4);
   delay(delaytime);
  */
}

long wait = 0;
void Nunchuck(){
  if (wait < millis()){
    wait = millis() + 100;
    Wire.requestFrom (0x52, 6);	// request data from nunchuck
    while (Wire.available ())
    {
      outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());	// receive byte as an integer
      cnt++;
    }

    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5)
    {
      print ();
    }

    cnt = 0;
    send_zero (); // send the request for next bytes
  }
}

void nunchuck_init ()
{
  Wire.beginTransmission (0x52);	// transmit to device 0x52
  Wire.send (0x40);		// sends memory address
  Wire.send (0x00);		// sends sent a zero.
  Wire.endTransmission ();	// stop transmitting
}

void send_zero ()
{
  Wire.beginTransmission (0x52);	// transmit to device 0x52
  Wire.send (0x00);		// sends one byte
  Wire.endTransmission ();	// stop transmitting
}

void print ()
{

  joy_x_axis = outbuf[0];
  joy_y_axis = outbuf[1];
  accel_x_axis = outbuf[2] * 2 * 2;
  accel_y_axis = outbuf[3] * 2 * 2;
  accel_z_axis = outbuf[4] * 2 * 2;

  z_button = 0;
  c_button = 0;

  if ((outbuf[5] >> 0) & 1)
  {
    z_button = 1;
  }
  if ((outbuf[5] >> 1) & 1)
  {
    c_button = 1;
  }

  if ((outbuf[5] >> 2) & 1)
  {
    accel_x_axis += 2;
  }
  if ((outbuf[5] >> 3) & 1)
  {
    accel_x_axis += 1;
  }

  if ((outbuf[5] >> 4) & 1)
  {
    accel_y_axis += 2;
  }
  if ((outbuf[5] >> 5) & 1)
  {
    accel_y_axis += 1;
  }

  if ((outbuf[5] >> 6) & 1)
  {
    accel_z_axis += 2;
  }
  if ((outbuf[5] >> 7) & 1)
  {
    accel_z_axis += 1;
  }
}

char nunchuk_decode_byte (char x)
{
  x = (x ^ 0x17) + 0x17;
  return x;
}

void scrivi(byte primo, byte secondo, byte terzo, byte quarto, int n){

  //Imposto primobyte
  bitWrite(primobyte, 0, bitRead(secondo, 0));
  bitWrite(primobyte, 1, bitRead(secondo, 1));
  bitWrite(primobyte, 2, bitRead(secondo, 2));
  bitWrite(primobyte, 3, bitRead(secondo, 3));
  bitWrite(primobyte, 4, bitRead(primo, 0));
  bitWrite(primobyte, 5, bitRead(primo, 1));
  bitWrite(primobyte, 6, bitRead(primo, 2));
  bitWrite(primobyte, 7, bitRead(primo, 3));

  //Imposto secondobyte
  bitWrite(secondobyte, 0, bitRead(quarto, 0));
  bitWrite(secondobyte, 1, bitRead(quarto, 1));
  bitWrite(secondobyte, 2, bitRead(quarto, 2));
  bitWrite(secondobyte, 3, bitRead(quarto, 3));
  bitWrite(secondobyte, 4, bitRead(terzo, 0));
  bitWrite(secondobyte, 5, bitRead(terzo, 1));
  bitWrite(secondobyte, 6, bitRead(terzo, 2));
  bitWrite(secondobyte, 7, bitRead(terzo, 3));

  if(n == 1){
    sommagriglia();
  }

  inviadati();
}

void sommagriglia(){
  //Unisco 4° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(secondobyte, i, (griglia[1][converti(i)] || bitRead(secondobyte, i)));
  };    

  //Unisco 3° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(secondobyte, i+4, (griglia[2][converti(i)] || bitRead(secondobyte, i+4)));
  };

  //Unisco 2° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(primobyte, i, (griglia[3][converti(i)] || bitRead(primobyte, i)));
  };    

  //Unisco 1° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(primobyte, i+4, (griglia[4][converti(i)] || bitRead(primobyte, i+4)));
  };
}

//Funzione che permette di convertire un valore per
//la somma fra griglia e byte
int converti(int n){
  switch(n){
  case 0:
    return 4;
    break;

  case 1:
    return 3;
    break;

  case 2:
    return 2;
    break;

  case 3:
    return 1;
    break;

  }
}

//Funzione che invia dati tramite seriale
void inviadati(){

  digitalWrite(catodo, HIGH);

  //Scrivo sul secondo 74164
  for (int i = 0; i <= 7; i++){
    digitalWrite(datapin, bitRead(secondobyte, i));

    //Impulso per il clock
    digitalWrite(clockpin, HIGH);
    digitalWrite(clockpin, LOW);
  }

  //scrivo sul primo 74164
  for (int i = 0; i <= 7; i++){
    digitalWrite(datapin, bitRead(primobyte, i));

    //Impulso per il clock
    digitalWrite(clockpin, HIGH);
    digitalWrite(clockpin, LOW);
  }

  digitalWrite(catodo, LOW);
}

//Funzione per dare coordinate XY di un punto

void point(byte x, byte y){

  primo_point = B0000;
  secondo_point = B0000;
  terzo_point = B0000;
  quarto_point = B0000;

 findxpos(x);

  switch (y){
  case 1:
    quarto_point += xpos;
    break;

  case 2:
    terzo_point += xpos;
    break;

  case 3:
    secondo_point += xpos;
    break;

  case 4:
    primo_point += xpos;
    break;

  default:
    scrivi(B1001, B0110, B0110, B1001, 1);
    break;
  }

    scrivi(primo_point, secondo_point, terzo_point, quarto_point, 1);
  }

void findxpos(byte x){
  xpos = B0000;

  switch(x){
  case 1:
    xpos = B1000;
    break;

  case 2:
    xpos = B0100;
    break;

  case 3:
    xpos = B0010;
    break;

  case 4:
    xpos = B0001;
    break;
  }
}

void lampeggia(int n){
  if (n == 0){
    digitalWrite(catodo, HIGH); //Spegne
    delay(250);
    digitalWrite(catodo, LOW); //Accende
    delay(250);
  }
  else{
    for(int i = 0; i < n; i++){
      digitalWrite(catodo, HIGH); //Spegne
      delay(250);
      digitalWrite(catodo, LOW); //Accende
      delay(250);
    }
  }
}

void set(int x, int y){
  griglia[y][x] = !bitRead(griglia[y][x], 0);
  sommagriglia();
  inviadati();
}

long wait_controllo = 0;
long wait_lampeggio = 0;
byte state = B0;
void controlloxy(){
  if (wait_controllo < millis()){
    wait_controllo = millis() + 300;

    if (posizione_x < 4){
      if(joy_x_axis > 178){
        posizione_x++;
      }
    }

    if(posizione_x > 1){
      if(joy_x_axis < 78){
        posizione_x--;
      }
    }

    if (posizione_y < 4){
      if(joy_y_axis > 178){
        posizione_y++;
      }
    }
    if(posizione_y > 1){
      if(joy_y_axis < 78){
        posizione_y--;
      }
    }
  }

if (state == 1)
  point(posizione_x, posizione_y);
 else
scrivi(B0,B0,B0,B0,1); 

if(wait_lampeggio < millis()){
  wait_lampeggio = millis() + 250;
  state = !state;
  }
}

Il pezzo di codice commentato nel loop è semplicemente un piccolo giochetto di luci.

Il codice può sembrare molto confuso poichè ho unito lo sketch per il nunchuck con lo sketch per la matrice.

E’ comunque un codice che andrebbe rivisto ma non credo che lo farò dato che ho già smontato tutto dalla breadboard per dare spazio al mio prossimo progetto! :)

Controllo matrice di LED 4×4 con Arduino e Nunchuck
Tags: