I've purchased 4X4X4 LED Light Cube kit from Aliexpress. ($3.79)
4X4X4 Blue LED Light Cube Kit 3D LED DIY Kit Electronic Suite for Arduino
You can get the instruction from here. but There is not enough information to complete the set.
Fortunately, got perfect info from this blog.
https://emalliab.wordpress.com/2015/07/24/icstation-4x4x4-led-cube-shield-for-arduino-software/
So I've followed it and could complete the set like this.
This is the blog (2nd one) explained about the source code.
icStation 4x4x4 LED Cube Shield for Arduino – Software
As described in my previous post, I now have a working (I’ve run the demo code!) icStation 4x4x4 LED cube shield connected up to an Arduino Uno. Unfortunately as I started to dig around in the sample library, I just couldn’t quite work out how it was meant to address each plane of the cube. Eventually I decided it wasn’t possible, due to a number of bugs in the code.
이전 게시물에서 설명한 것처럼, icStation 4x4x4 LED cube shield를 Arduino Uno에 연결하는 작업을 하고 있습니다. 불행하게도 샘플 라이브러리를 파고들 수록 큐브의 각 면을 지정하는 방법에 대해 이해하기가 더 어려워 졌습니다. 결국 해당 샘플 코드에 버그가 많아 제대로작동할 수 없다는 결론에 이르렀습니다.
The demo code worked as the code just showed the same pattern on each of the four planes. This is largely because the initialisation routines set the four Ardunio data pins to low, and then never did anything else with them! There is some mention of pins 16 and 17, but no mention of pins 18 and 19, and actually in the main display routines, there is nothing done to actually set any of these pins once initialisation is complete. So at this point I decided to read a bit more about the 74HC595 and just go it alone. Attached is the result. Feel free to use as you see fit.
그 데모 코드는 4개의 면 각각이 동일한 패턴으로 보여지도록 작동하고 있습니다. 초기화 루틴이 4 개의 Ardunio 데이터 핀을 로우로 설정 한 후 그것을 아무곳에서도 사용하지 않습니다. 핀 16과 핀 17에 대해서는 언급이 있지만, 핀 18과 19에 대한 언급이 없습니다, 메인 디스플레이 루틴에서, 초기화가 완료되면 실제로 이러한 핀들을 설정하는 일은 없습니다. 그래서 이 시점에서 필자는 74HC595에 대해 좀 더 읽고 혼자서 결정했습니다. 첨부 된 결과입니다. 이것을 토대로 당신이 적합하다고 생각하는대로 자유롭게 사용하십시오.
Basic initialisation
The two shift registers seem fairly simple to setup. The Arduino needs some control pins setting up as outputs alongside the four digital outs used for the LEDs. The initialisation is quite straight forward as follows:
두 개의 시프트 레지스터는 설정하는 것이 매우 간단합니다. Arduino는 LED에 사용되는 4 개의 디지털 출력과 함께 출력으로 설정되는 일부 제어 핀을 필요로합니다. 초기화는 다음과 같이 매우 간단합니다.
#include <Arduino.h> int HC595_clockPin=0; // SH_CP of 74HC595 int HC595_latchPin=1; // ST_CP of 74HC595 int HC595_dataPin=3; // DS of 74HC595 int HC595_enablePin=2; // Not OE of 74HC595 int LED_Pin16= 4; int LED_Pin17= 5; int LED_Pin18= 6; int LED_Pin19= 7; void setup() { // put your setup code here, to run once: pinMode( HC595_latchPin, OUTPUT ); pinMode( HC595_clockPin, OUTPUT ); pinMode( HC595_dataPin, OUTPUT ); pinMode( HC595_enablePin, OUTPUT ); pinMode( LED_Pin16, OUTPUT ); pinMode( LED_Pin17, OUTPUT ); pinMode( LED_Pin18, OUTPUT ); pinMode( LED_Pin19, OUTPUT ); digitalWrite(LED_Pin16,HIGH); digitalWrite(LED_Pin17,HIGH); digitalWrite(LED_Pin18,HIGH); digitalWrite(LED_Pin19,HIGH); // digitalWrite(HC595_enablePin, LOW); // Enable Not OE (negative logic) }
I never did quite work out if I needed to do anything with the enable pin, but as it is active low, I assumed that by not doing anything, everything would be enabled by default anyway.
enable pin과 관련해서는 아무것도 하지 않았습니다. active 상태 값이 low 이기 때문입니다. 이렇게 아무것도 정의하지 않으면 디폴트로 enable이 될 것으로 생각 됩니다.
In terms of actually writing a value to the 74HC595, again that is fairly straight forward.
74HC595에 적용된 값들은 그냥 보시는 대로 입니다.
/*
Protocol for sending the data to the hc595 is as follows:
(see: http://www.arduino.cc/en/Tutorial/ShiftOut)
"when the clock pin goes from low to high, the shift register
reads the state of the data pin ... when the latch pin goes
from low to high the sent data gets moved from the shift
registers ... to the output pins"
As we have two HC595s chained together, we use a 16 bit input value
*/
void write_74HC595 (unsigned int hc595value) {
digitalWrite(HC595_latchPin, LOW); // ensures LEDs don't light whilst changing values
// Shift each 8 bit value in sequence - the two chained HC595s automatically grab
// the right bits - the first 8 to the first chip, second 8 to the second chip
shiftOut(HC595_dataPin, HC595_clockPin, LSBFIRST, hc595value);
shiftOut(HC595_dataPin, HC595_clockPin, LSBFIRST, (hc595value >> 8));
digitalWrite(HC595_latchPin, HIGH); // data transferred from shift register to outputs when latch goes LOW->HIGH
}
So 16 bits of the hc595value variable are sent in two 8-bit chunks over the serial port to the shift registers and with the appropriate signalling via the latch pin, that is basically that. This sets the outputs of the 74HC595 to high, but in order to make the LEDs come on, the Arduino data pins corresponding to the horizontal planes must be set low. If a different pattern is required for each plane, then some kind of simple ‘scanning’ is required as illustrated below.
따라서 hc595value 변수의 16 비트는 두 개의 8 비트 chunk로 직렬 포트를 통해 shift register로 전송 되며 이것은 latch pin을 통해 적절한 신호로 전송됩니다. 이것은 74HC595의 출력을 high로 설정하지만 LED를 켜기 위해 수평면에 해당하는 Arduino 데이터 핀을 low로 설정 해야합니다. 각 평면에 다른 패턴이 필요한 경우 아래에 설명 된 것처럼 일종의 간단한 '스캐닝'이 필요합니다.
int LED_Plane[] = {LED_Pin16, LED_Pin17, LED_Pin18, LED_Pin19}; /* Inputs: Array of 4 integers - one for each plane */ void display (unsigned int *pPattern) { int i; for (i=0; i<4; i++) { int j; for (j=0; j<1000; j++) { // Slow this down so that there is time for the LEDS to light // Experimentation shows that 200+ gives brighter LEDs // NB: Do it this way so an empty loop isn't optimised out if (j==0) { digitalWrite(LED_Plane[0], HIGH); digitalWrite(LED_Plane[1], HIGH); digitalWrite(LED_Plane[2], HIGH); digitalWrite(LED_Plane[3], HIGH); write_74HC595 (pPattern[i]); digitalWrite(LED_Plane[i], LOW); } } } }
I guess the only thing to really note here is that without the loop involving j then the ‘scanning’ was happening too fast to allow the LEDs to have any significant brightness at all. I initially had a simple for (j=0; j<1000; j++) {}; statement at the end, but this seemed to be optimised out – at least it didn’t seem to have the delay effect I wanted, so instead I made the code only act on one pass through the loop.
여기서 정말로 주목할 것은, j를 포함하는 루프가 없으면 '스캐닝'이 너무 빠르게 진행 되어 LED가 충분히 밝게 되지 않는 다는 겁니다. 나는 처음에는 간단한 for 문을 (j = 0; j <1000; j ++) {}; 를 끝에 사용했습니다. 이것이 최적화 된 것처럼 보였지만 내가 원한 delay 효과를 보여주지는 못했습니다. 그래서 그렇게 하는 대신에 loop를 통과하는 것을 한번만 실행되도록 코딩했습니다.
So, with these basics, it is now possible to get a 64 bit pattern, in the form of four 16 bit values, each representing one plane of 16 LEDs, onto the cube.
이렇게 함으로서 64 bit pattern이 가능해 졌습니다. 4개의 16 비트 값 형태로 각각이 큐브의 16 LEDs 의 한 평면을 나타내게 됩니다.
I have the full demo code file below – it isn’t massively pretty, and its not cpp (sorry – I’ve always been more of a C person I’m afraid, and my C is a little rusty), but it works for me. Your proverbial mileage, as they say, may vary.
아래에 전체 코드가 있습니다. 코드가 깔끔하지 않고 cpp 로 돼 있지 않습니다. (나는 C 언어에 대해 그렇게 능숙하지가 못해서요.) 아무튼 이 소스코드는 잘 작동합니다.
Kevin
#include <Arduino.h>
int HC595_clockPin=0; // SH_CP of 74HC595
int HC595_latchPin=1; // ST_CP of 74HC595
int HC595_dataPin=3; // DS of 74HC595
int HC595_enablePin=2; // Not OE of 74HC595
int LED_Pin16= 4;
int LED_Pin17= 5;
int LED_Pin18= 6;
int LED_Pin19= 7;
int LED_Plane[] = {LED_Pin16, LED_Pin17, LED_Pin18, LED_Pin19};
// Each line (8 bytes) is an entire cube, with two consecutive bytes per plane of LEDS,
// and 16 LEDS per plane. LEDs are encoded in the following order:
// Lowest plane byte 1, lowest plane byte 2, second lowerst plane 1, then 2,
// second from top plane 1, then 2, highest plane 1, highest plane 2.
//
// Each plane is encoded looking at the Arduino oriented with the USB/power
// designated by 'south' by started 'north west' as follows:
// D0 D1 D2 D3
// D4 D5 D6 D7
// D8 D9 D10 D11
// D12 D13 D14 D15
//
// D16 D17 D18 D19
// (USB) (Power)
// With D16 being the lowest plane, through to D19 being the highest plane
// Of course, if you wire the planes up differently, that is up to you!
//
// Each two bytes of the pattern are therefore:
// B00000000, B00000000 -> D0-7, D8-15
// with D0 = msb of the first value, D7 being the lsb of the first value,
// and D8 = msb of the second value, D15 being the lsb of the second value.
//
// So the entire pattern is:
// B10010000,B00001001,B00000000,B00000000,B00000000,B00000000,B10010000,B00001001,
// | | | || | | | ||
// | | | |\ D15 bottom plane | | | |\ D15 top plane
// | | | \ D14 bottom plane | | | \ D14 top plane
// | | \ D8 bottom plane | | \ D8 top plane
// | \ D7 bottom plane | \ D7 top plane
// \ D0 bottom plane \ D0 top plane
//
// Comment following in or out to switch patterns in or out
#define SWAP 1
#define SNAKE 1
#define BURST 1
#define SPIRAL 1
#define ALT 1
unsigned char pattern[] = {
#ifdef SWAP
B10010000,B00001001,B00000000,B00000000,B00000000,B00000000,B10010000,B00001001,
B00000000,B00000000,B10010000,B00001001,B10010000,B00001001,B00000000,B00000000,
B00000000,B00000000,B01100000,B00000110,B01100000,B00000110,B00000000,B00000000,
B01100000,B00000110,B00000000,B00000000,B00000000,B00000000,B01100000,B00000110,
B00001001,B10010000,B00000000,B00000000,B00000000,B00000000,B00001001,B10010000,
B00000000,B00000000,B00001001,B10010000,B00001001,B10010000,B00000000,B00000000,
B00000000,B00000000,B00000110,B01100000,B00000110,B01100000,B00000000,B00000000,
B00000110,B01100000,B00000000,B00000000,B00000000,B00000000,B00000110,B01100000,
#endif
#ifdef SNAKE
B11001100,B00000000,B11001100,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11001100,B00000000,B11001100,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,B11001100,B00000000,
B00000000,B00000000,B00000000,B00000000,B00001100,B11000000,B00001100,B11000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,B11001100,
B00000000,B00000000,B00000000,B00000000,B00000000,B01100110,B00000000,B01100110,
B00000000,B00000000,B00000000,B00000000,B00000000,B00110011,B00000000,B00110011,
B00000000,B00000000,B00000000,B00110011,B00000000,B00110011,B00000000,B00000000,
B00000000,B00110011,B00000000,B00110011,B00000000,B00000000,B00000000,B00000000,
B00000011,B00110000,B00000011,B00110000,B00000000,B00000000,B00000000,B00000000,
B00110011,B00000000,B00110011,B00000000,B00000000,B00000000,B00000000,B00000000,
B01100110,B00000000,B01100110,B00000000,B00000000,B00000000,B00000000,B00000000,
#endif
#ifdef BURST
B00000000,B00000000,B00000110,B01100000,B00000110,B01100000,B00000000,B00000000,
B00000110,B01100000,B01101001,B10010110,B01101001,B10010110,B00000110,B01100000,
B01101001,B10010110,B10010000,B00001001,B10010000,B00001001,B01101001,B10010110,
B10010000,B00001001,B00000000,B00000000,B00000000,B00000000,B10010000,B00001001,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
#endif
#ifdef SPIRAL
B11001100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B01100110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00110011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000011,B00110000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00110011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B01100110,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B11001100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00001100,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B11001100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11001100,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B01100110,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00110011,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000011,B00110000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00110011,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B01100110,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B11001100,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00001100,B11000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11001100,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B01100110,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00110011,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000011,B00110000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00110011,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B01100110,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00001100,B11000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01100110,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110011,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B00110000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00110011,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01100110,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11001100,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001100,B11000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B11001100,B00000000,
#endif
#ifdef ALT
B11111001,B10011111,B10010000,B00001001,B10010000,B00001001,B11111001,B10011111,
B00000110,B01100000,B01101001,B10010110,B01101001,B10010110,B00000110,B01100000,
B00000000,B00000000,B00000110,B01100000,B00000110,B01100000,B00000000,B00000000,
B00000110,B01100000,B01101001,B10010110,B01101001,B10010110,B00000110,B01100000,
#endif
};
int patternNumber=0;
int numPatterns=sizeof(pattern)/8;
int tickCount=0;
int tickCountMax=50; // How many times to loop before changing the pattern
unsigned int currentPattern[4];
void setup() {
// put your setup code here, to run once:
pinMode( HC595_latchPin, OUTPUT );
pinMode( HC595_clockPin, OUTPUT );
pinMode( HC595_dataPin, OUTPUT );
pinMode( HC595_enablePin, OUTPUT );
pinMode( LED_Pin16, OUTPUT );
pinMode( LED_Pin17, OUTPUT );
pinMode( LED_Pin18, OUTPUT );
pinMode( LED_Pin19, OUTPUT );
digitalWrite(LED_Pin16,HIGH);
digitalWrite(LED_Pin17,HIGH);
digitalWrite(LED_Pin18,HIGH);
digitalWrite(LED_Pin19,HIGH);
// digitalWrite(HC595_enablePin, LOW); // Enable Not OE (negative logic)
patternNumber=0;
tickCount = tickCountMax;
}
/*
Protocol for sending the data to the hc595 is as follows:
(see: http://www.arduino.cc/en/Tutorial/ShiftOut)
"when the clock pin goes from low to high, the shift register
reads the state of the data pin ... when the latch pin goes
from low to high the sent data gets moved from the shift
registers ... to the output pins"
As we have two HC595s chained together, we use a 16 bit input value
*/
void write_74HC595 (unsigned int hc595value) {
digitalWrite(HC595_latchPin, LOW); // ensures LEDs don't light whilst changing values
// digitalWrite(HC595_enablePin, HIGH); // OE is negative logic
// Shift each 8 bit value in sequence - the two chained HC595s automatically grab
// the right bits - the first 8 to the first chip, second 8 to the second chip
shiftOut(HC595_dataPin, HC595_clockPin, LSBFIRST, hc595value);
shiftOut(HC595_dataPin, HC595_clockPin, LSBFIRST, (hc595value >> 8));
digitalWrite(HC595_latchPin, HIGH); // data transferred from shift register to outputs when latch goes LOW->HIGH
// digitalWrite(HC595_enablePin, LOW); // re-enable (negative logic again)
}
/*
Inputs: Array of 4 integers - one for each plane
*/
void display (unsigned int *pPattern)
{
int i;
for (i=0; i<4; i++)
{
int j;
for (j=0; j<1000; j++)
{
// Slow this down so that there is time for the LEDS to light
// Experimentation shows that 200+ gives brighter LEDs
// NB: Do it this way so an empty loop isn't optimised out
if (j==0)
{
digitalWrite(LED_Plane[0], HIGH);
digitalWrite(LED_Plane[1], HIGH);
digitalWrite(LED_Plane[2], HIGH);
digitalWrite(LED_Plane[3], HIGH);
write_74HC595 (pPattern[i]);
digitalWrite(LED_Plane[i], LOW);
}
}
}
}
void displayPattern ()
{
int i;
// only update it every tick otherwise just display as is
tickCount--;
if (tickCount <= 0)
{
tickCount = tickCountMax;
for (i=0; i<4; i++)
{
currentPattern[i] = pattern[i*2 + patternNumber*8] * 256 + pattern[i*2 + 1 + patternNumber*8];
}
patternNumber++;
if (patternNumber >= numPatterns)
{
patternNumber = 0;
}
}
display(¤tPattern[0]);
}
void loop() {
// put your main code here, to run repeatedly:
displayPattern();
}
'IoT > Arduino' 카테고리의 다른 글
[Arduino Project 2] LED Light stand for 3D Crystal laser cube Ver. 0.4 (0) | 2017.05.08 |
---|---|
[I don't like you] practice project for the project 'I like you' (0) | 2017.05.07 |
MIT App Inventor - Android App - Mega Millions Jackpot number generator (0) | 2017.01.30 |
Updated Source Code - Automated Mung Bean Sprouts Growing Machine (0) | 2017.01.27 |
Arduino Project 1 - Automated Mung Bean Sprouts Growing Machine (0) | 2017.01.23 |
[Arduino] Motion Sensor and Water Level Sensor (0) | 2017.01.17 |
[Arduino] Joystick, LED Dot Matrix and ADXL335 Module (0) | 2017.01.17 |
[Arduino] Ultrasonic, Keypad and Temperature and Humidity Sensor (0) | 2017.01.15 |
[Arduino] 7 Segment, Servo, LCD and Thermometer (0) | 2017.01.14 |
[Arduino] Using 74HC595 8-bit serial-in/serial or parallel-out shift register (0) | 2017.01.12 |