sobota, 16 listopada 2013

Raspberry Pi - biblioteka GPIO WiringPi + rejestr przesuwający 74x595 + efekt świetlny "Matrix"

Ten mini projekt powstał w celach wyłącznie edukacyjnych.  Podczas zabaw z Raspberry Pi znalazłem świetną bibliotekę Wiring Pi do obsługi sprzętowych portów GPIO. Na stronie autora znaleźć można doskonałą dokumentację i przykłady zastosowania. Biblioteka została napisana w języku C.
Aby sprawdzić działanie biblioteki należy zainstalować ją wg. instrukcji ze strony autora. Po przeprowadzonej instalacji i wydaniu polecenia:
gpio readall
wyświetli się lista wszystkich portów GPIO w naszym Raspberry Pi. Należy zwrócić szczególną uwagę na numerację wyprowadzeń wykorzystywaną w bibliotece - różni się ona od oznaczeń fabrycznych.

Do prostego przetestowania możliwości biblioteki wykorzystałem rejestr przesuwający 74x595, który sterowany jest za pomocą sprzętowego interfejsu SPI wbudowanego w Raspberry Pi. Przesłane dane są zatrzaskiwane za pomocą wejścia rejestru z etykietą LATCH obsługiwanego zwykłym wyprowadzeniem I/O (zatrzaskiwanie danych można zrealizować także za pomocą sprzętowego sygnału CEx interfejsu SPI). Dwukolorowa matryca LED posiada 8 wyprowadzeń do sterowania poszczególnymi kolumnami (4 czerwone i 4 zielone). Poszczególne kolumny aktywowane są tranzystorami NPN (matryca ze wspólną katodą). Aby uprościć oprogramowanie kolumny zostały połączone z kolejnymi wyprowadzeniami I/O Raspberry Pi (wg. numeracji biblioteki WiringPi). Sygnały oznaczone etykietami S1-S4 sterują kolejnymi  kolumnami diod czerwonych, natomiast sygnały S5-S8 kolumnami diod zielonych. Takie podłączenie umożliwia także łatwą realizację innych efektów świetlnych. Poszczególne wiersze sterowane są za pomocą rejestru przesuwającego. 

Schemat całości przedstawia się następująco:
Ponieważ testy przeprowadzone są na płytce Raspberry Pi w wersji 2.0 sygnał LATCH został podłączony do portu I/O złącza P2 (starsze wersje nie posiadają tego złącza - należy skorzystać z innego wyprowadzenia).
Po zmontowaniu na płytce stykowej całość przedstawia się następująco:



Efekt świetlny "Matrix" uzyskany za pomocą prostego oprogramowania (omówionego poniżej):

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include "../../wiringPi/wiringPi.h"
#include "../../wiringPi/wiringPiSPI.h"

#define LATCH 17  //numer wyprowadzenia (wg wiringPi) pracujacego jako zatrzask

unsigned char buf;
unsigned char buf_tmp;
unsigned int i,j,k;

int main (){
  wiringPiSetup();
  wiringPiSPISetup (1, 1000000);
  pinMode(LATCH, OUTPUT);
  for(i=0; i < 8; i++) pinMode(i, OUTPUT);
  for(i=0; i < 8; i++) digitalWrite(i, 0);

 while(1){
  for(j=0; j < 8 ; j++ ){
  srand(millis());
  k = rand()%8; // liczba z zakresu 0-7
  digitalWrite(k, 1); //wysteruj odpowiednia katode
    for (i=0; i < 8; i++){
    buf_tmp = 1 << i;
    buf = buf_tmp;
    wiringPiSPIDataRW(1,&buf,1);
    digitalWrite(LATCH,1);
    digitalWrite(LATCH,0);
    delay (70);
     }
  digitalWrite(k, 0); //wygas katode
  buf_tmp = buf = 0;
  wiringPiSPIDataRW(1,&buf,1); //wyslij 0 - usuniecie cieni
  }
 }
}
Do poprawnej kompilacji i działania programu konieczne jest dodanie plików nagłówkowych umożliwiających sterowanie wyjściami I/O oraz interfejsem SPI (wiersze 5,6 listingu). Na początku programu konieczne jest wywołanie funkcji konfigurujących (w. 15,16). Ze względu na podłączenie tranzystorów sterujących katodami matrycy led (odpowiednie kolumny) do kolejnych wyprowadzeń (od 0 do 7) w bardzo wygodny sposób można było wykonać ich konfigurację za pomocą pętli for (w. 18,19). Pętla główna programu while(1) składa się z dwóch zagnieżdżonych pętli for. Pierwsza odpowiada za wybór kolejnej kolumny, natomiast druga - kolejnego wiersza (diody). Ponieważ program powstał na bazie nieco innego efektu, polecam zakomentować linie 23 i 24 na listingu, a w wierszu 25 zmienną k zamienić na j.
Funkcja srand() jest inicjalizowana za pomocą liczby milisekund jakie upłynęły od uruchomienia programu - jest to jedna z funkcji biblioteki wiringPi. Wiersze 30,31 odpowiadają za wygenerowanie impulsu zatrzaskującego - LATCH. Ponieważ funkcja wiringPiSPIDataRW() modyfikuje drugi parametr (zapisuje odebrane dane z interfejsu SPI) wprowadzono dodatkową zmienną buf_tmp. Po "dojściu" do ostatniego wiersza matrycy led wygaszana jest cała kolumna (katoda), zerowane bufory (w. 35)  oraz wszystkie wyjścia rejestru przesuwającego ustawiane w stan niski (w. 36).  Ostatnia czynność jest konieczna ze względu na powstające tzw. "duszki" na ostatniej diodzie przy zmianie aktywnej kolumny.

Kompilacja programu następuje po wykonaniu poleceń:
gcc -Wall -o program program.c -lwiringPi
./program

Przed uruchomieniem tak skompilowanego programu konieczne jest jeszcze aktywowanie sprzętowego interfejsu SPI za pomocą polecenia:
gpio load spi


Polecam zapoznanie się z pozostałymi funkcjami biblioteki wiringPi. Wszystkie potrzebne informacje znajdziecie w bardzo dobrej dokumentacji na stronie autora.

Powodzenia :)
Michał