블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 받은 트랙백

글 보관함

calendar

  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      


The Hamcrest Tutorial



Introduction

Hamcrest is a framework for writing matcher objects allowing 'match' rules to be defined declaratively. There are a number of situations where matchers are invaluble, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use Hamcrest for unit testing.


Hamcrest는 'match'rule을 선언적으로 정의 해 matcher objects를 작성하기위한 framework입니다. UI 유효성 UI validation 또는 데이터 필터링과 같이 matchers가 사용할 수 없는 상황도 많이 있지만 matcher가 가장 일반적으로 사용되는 곳은 flexible tests를 작성하는 영역에 있습니다. 이 tutorial에서는 unit testing를 위해 Hamcrest를 사용하는 방법을 보여줍니다.


When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right". Such tests fail when the behaviour of the aspect under test deviates from the expected behaviour, yet continue to pass when minor, unrelated changes to the behaviour are made.


테스트를 작성할 때 테스트를 지나치게 자세하게 지정하는 것 (그리고 수정이 어렵게 하는 것)과 충분한 테스트를 하지 않는 것 사이의 균형을 잡기가 어렵기 때문에 (이럴 경우 테스트 대상에 문제가 생긴 경우에도 테스트가 pass 될 수 있어 해당 테스트가 유효하지 않게 됩니다.) 테스트 할 aspect를 정확하게 선택할 수 있도록 하고, 가져야 할 값을 describe 해서 정밀하게 제여할 수 있도록 하는 도구를 사용하면 "just right" 테스트를 작성하는 데 크게 도움이됩니다. 이러한 테스트는 테스트중인 aspect의 동작이 예상되는 벗어나는 경우 fail 하고 , minor 한 변화나 테스트 범위에서 벗어난 변경이 있는 경우 pass 해야 합니다.



My first Hamcrest test

We'll start by writing a very simple JUnit 3 test, but instead of using JUnit's assertEquals methods, we use Hamcrest's assertThatconstruct and the standard set of matchers, both of which we statically import:


아래 간단한 JUnit 3 test를 작성할 겁니다. JUnit의 assertEquals methods를 사용하는 대신에 Hamcrest의 assertThat construct와 matchers의 표준 세트를 사용할 겁니다. 이 둘은 정적으로 import 합니다.



``` import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*;


import junit.framework.TestCase;


public class BiscuitTest extends TestCase { public void testEquals() { Biscuit theBiscuit = new Biscuit("Ginger"); Biscuit myBiscuit = new Biscuit("Ginger"); assertThat(theBiscuit, equalTo(myBiscuit)); } } ```



The assertThat method is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object biscuit that is the first method parameter. The second method parameter is a matcher for Biscuit objects, here a matcher that checks one object is equal to another using the Object equals method. The test passes since the Biscuit class defines an equals method.


assertThat method는 test assertion을 만들기 위한 양식화 된 문장입니다. 이 예에서는 assertion의 subject는 첫 번째 method 매개 변수 인 object biscuit입니다. 두 번째 method 매개 변수는 Biscuit objects에 대한 matcher입니다. 여기에서 한 object를 검사하는 matcher는 Object equals method를 사용하는것과 같습니다. 이 테스트는 Biscuit 클래스가 equals method를 정의하기 때문에 pass 하게 됩니다.



If you have more than one assertion in your test you can include an identifier for the tested value in the assertion:


하나 이상의 assertion이 있는 경우 테스트 된 값에 대한 identifier를 assertion에 포함 할 수 있습니다.


assertThat("chocolate chips", theBiscuit.getChocolateChipCount(), equalTo(10)); assertThat("hazelnuts", theBiscuit.getHazelnutCount(), equalTo(3));



Other test frameworks



Hamcrest has been designed from the outset to integrate with different unit testing frameworks. For example, Hamcrest can be used with JUnit 3 and 4 and TestNG. (For details have a look at the examples that come with the full Hamcrest distribution.) It is easy enough to migrate to using Hamcrest-style assertions in an existing test suite, since other assertion styles can co-exist with Hamcrest's.


Hamcrest는 처음부터 다른 unit testing framework와 통합되도록 설계되었습니다. 예를 들어, Hamcrest는 JUnit 3과 4 및 TestNG와 함께 사용할 수 있습니다. (자세한 내용은 전체 Hamcrest distribution과 함께 제공되는 예제를 참조하십시오.) 다른 assertion 스타일이 Hamcrest와 같이 사용될 수 있기 때문에 기존 test suite에서 Hamcrest-style assertions를 사용하는 것으로 마이그레이션하는 것은 쉽습니다.


Hamcrest can also be used with mock objects frameworks by using adaptors to bridge from the mock objects framework's concept of a matcher to a Hamcrest matcher. For example, JMock 1's constraints are Hamcrest's matchers. Hamcrest provides a JMock 1 adaptor to allow you to use Hamcrest matchers in your JMock 1 tests. JMock 2 doesn't need such an adaptor layer since it is designed to use Hamcrest as its matching library. Hamcrest also provides adaptors for EasyMock 2. Again, see the Hamcrest examples for more details.


Hamcrest는 또한 mock objects framework와 같이 사용 될 수 있습니다. 그러려면 mock objects framework의 matcher와 Hamcrest의 matcher 에 대한 concept을 연결해 주도록 adaptors를 사용하면 됩니다. 예를 들어, JMock 1의 constraints는 Hamcrest의 matchers입니다. Hamcrest는 JMock 1 테스트에서 Hamcrest matchers를 사용할 수 있도록 JMock 1 어댑터를 제공합니다. JMock 2는 Hamcrest를 매칭 라이브러리로 사용하기 때문에 그러한 adaptor layer가 필요하지 않습니다. Hamcrest는 EasyMock 2 용 어댑터도 제공합니다. 자세한 내용은 Hamcrest 예제를 참조하십시오.



A tour of common matchers



Hamcrest comes with a library of useful matchers. Here are some of the most important ones.


Hamcrest는 유용한 matchers 라이브러리를 제공합니다. 그 중에 중요한 것들 입니다.



    Core
    • anything - always matches, useful if you don't care what the object under test is
    • describedAs - decorator to adding custom failure description
    • is - decorator to improve readability - see "Sugar", below

  • Logical
    • allOf - matches if all matchers match, short circuits (like Java &&)
    • anyOf - matches if any matchers match, short circuits (like Java ||)
    • not - matches if the wrapped matcher doesn't match and vice versa

  • Object
    • equalTo - test object equality using Object.equals
    • hasToString - test Object.toString
    • instanceOfisCompatibleType - test type
    • notNullValuenullValue - test for null
    • sameInstance - test object identity

  • Beans
    • hasProperty - test JavaBeans properties

  • Collections
    • array - test an array's elements against an array of matchers
    • hasEntryhasKeyhasValue - test a map contains an entry, key or value
    • hasItemhasItems - test a collection contains elements
    • hasItemInArray - test an array contains an element

  • Number
    • closeTo - test floating point values are close to a given value
    • greaterThangreaterThanOrEqualTolessThanlessThanOrEqualTo - test ordering

  • Text
    • equalToIgnoringCase - test string equality ignoring case
    • equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
    • containsStringendsWithstartsWith - test string matching



Sugar


Hamcrest strives to make your tests as readable as possible. For example, the is matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent:


Hamcrest는 여러분이 최대한 readable한 테스트를 만들 수 있도록 노력합니다. 예를 들어, is matcher는 기본이되는 matcher에 추가의 동작을 추가하지 않는 wrapper 입니다. (어떤 동작을 하지는 않고 단지 가독성 -readable- 을 제공하기 위한 것).

아래 assertion 들은 다 똑 같습니다.



assertThat(theBiscuit, equalTo(myBiscuit)); assertThat(theBiscuit, is(equalTo(myBiscuit))); assertThat(theBiscuit, is(myBiscuit));


The last form is allowed since is(T value) is overloaded to return is(equalTo(value)).


마지막 form은 is(T value)가 is(equalTo (value))를 return하도록 overload 되어 있기 때문에 가능합니다.



Writing custom matchers



Hamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable!


Hamcrest는 많은 유용한 matchers와 함께 번들로 제공되지만, 테스트 요구에 맞추기 위해 수시로 자신 만의 템플릿을 만들어야 할 필요가있을 것입니다. 이것은 일반적으로  동일한 properties set을 반복적으로 테스트 하는 (다른 테스트 들에서도) code의 fragment를 발견 했을 때 그리고 이 fragment를 단일 assertion으로 묶으려는 경우에 해당 될 겁니다. 자신 만의 matcher를 작성함으로써 코드 중복을 제거하고 테스트의 가독성을 훨씬 높일 수 있습니다!



Let's write our own matcher for testing if a double value has the value NaN (not a number). This is the test we want to write:


double 값의 값이 NaN (숫자가 아님) 인 경우를 테스트하기 위해 자체 matcher를 작성해 보겠습니다. 아래 그 예제가 있습니다.



public void testSquareRootOfMinusOneIsNotANumber() { assertThat(Math.sqrt(-1), is(notANumber())); }


And here's the implementation:


``` package org.hamcrest.examples.tutorial;

import org.hamcrest.Description; import org.hamcrest.Factory; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher;

public class IsNotANumber extends TypeSafeMatcher {

@Override public boolean matchesSafely(Double number) { return number.isNaN(); }

public void describeTo(Description description) { description.appendText("not a number"); }

@Factory public static Matcher notANumber() { return new IsNotANumber(); }

} ```



The assertThat method is a generic method which takes a Matcher parameterized by the type of the subject of the assertion. We are asserting things about Double values, so we know that we need a Matcher<Double>. For our Matcher implementation it is most convenient to subclass TypeSafeMatcher, which does the cast to a Double for us. We need only implement the matchesSafely method - which simply checks to see if the Double is NaN - and the describeTo method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks:


assertThat method는, assertion의 subject의 type에 의해 파라미터 화 된 Matcher를 취하는 generic method입니다. 우리는 Double 값에 대해 asserting하고 있으므로 Matcher <Double>이 필요하다는 것을 알고 있습니다. 이 Matcher를 구현하는데 있어 TypeSafeMatcher를 서브 클래스로 implement 하는 것이 가장 좋습니다. TypeSafeMatcher는 Double로 형변환을 하게 됩니다. matchesSafely method와 describeTo method만 implement 하면 됩니다. matchesSafely method는 단순히 Double이 NaN인지 확인하고 describeTo method 테스트가 fail 할 경우 오류 메시지를 생성하는 데 사용됩니다. 다음은 failure message가 표시되는 예입니다.



assertThat(1.0, is(notANumber()));


fails with the message


java.lang.AssertionError: Expected: is not a number got : <1.0>



The third method in our matcher is a convenience factory method. We statically import this method to use the matcher in our test:


우리의 matcher에서 세 번째 method는 편리한 factory method 입니다. test에서 matcher를 사용하기 위해 이 method를 정적(statically)으로 가져옵니다.


``` import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*;

import static org.hamcrest.examples.tutorial.IsNotANumber.notANumber;

import junit.framework.TestCase;

public class NumberTest extends TestCase {

public void testSquareRootOfMinusOneIsNotANumber() { assertThat(Math.sqrt(-1), is(notANumber())); } } ```



Even though the notANumber method creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches.


비록 notANumber method가 호출 될 때마다 new matcher를 생성하지만, 이것이 matcher의 유일한 사용 patter 이라고 예단 해서는 안됩니다. 여러분은 이 matcher가 stateless 임을 유념해야 합니다. single instance 가 matcher들 사이에서 재사용 될 수 있습니다.



Sugar generation



If you produce more than a few custom matchers it becomes annoying to have to import them all individually. It would be nice to be able to group them together in a single class, so they can be imported using a single static import much like the Hamcrest library matchers. Hamcrest helps out here by providing a way to do this by using a generator.


여러가지 custom matchers를 만들었다면 이들을 각각 import 하는 일이 성가실 겁니다. 하나의 클래스에서 이들을 그룹화 하면 좋겠죠. 그렇게 하면 Hamcrest 라이브러리 matchers와 같이 single static import를 사용하여 한꺼번에 import 할 수 있을 겁니다. Hamcrest는 generator를 사용하여 이를 수행 할 수있는 방법을 제공합니다.


First, create an XML configuration file listing all the Matcher classes that should be searched for factory methods annotated with the org.hamcrest.Factory annotation. For example:


먼저, 모든 Matcher classes을 리스팅 한 XML configuration file을 생성합니다. 이것은 org.hamcrest.Factory annotation과 함께 factory methods annotated를 하기 위해 검색 될 겁니다. 예 :


```

```


Second, run the org.hamcrest.generator.config.XmlConfigurator command-line tool that comes with Hamcrest. This tool takes the XML configuration file and generates a single Java class that includes all the factory methods specified by the XML file. Running it with no arguments will display a usage message. Here's the output for the example.


둘째, Hamcrest와 함께 제공되는 org.hamcrest.generator.config.XmlConfigurator command-line tool를 실행하십시오. 이 도구는 XML 구성 파일을 사용하여 XML 파일에 지정된 모든 팩토리 method를 포함하는 단일 Java 클래스를 생성합니다. 인수없이 실행하면 사용법 메시지가 표시됩니다. 이 예제의 결과는 다음과 같습니다.



``` // Generated source. package org.hamcrest.examples.tutorial;

public class Matchers {

public static org.hamcrest.Matcher is(T param1) { return org.hamcrest.core.Is.is(param1); }

public static org.hamcrest.Matcher is(java.lang.Class param1) { return org.hamcrest.core.Is.is(param1); }

public static org.hamcrest.Matcher is(org.hamcrest.Matcher param1) { return org.hamcrest.core.Is.is(param1); }

public static org.hamcrest.Matcher notANumber() { return org.hamcrest.examples.tutorial.IsNotANumber.notANumber(); }

} ```



Finally, we can update our test to use the new Matchers class.


마지막으로 new Matchers class를 사용하도록 아래처럼 업데이트 합니다.



``` import static org.hamcrest.MatcherAssert.assertThat;

import static org.hamcrest.examples.tutorial.Matchers.*;

import junit.framework.TestCase;

public class CustomSugarNumberTest extends TestCase {

public void testSquareRootOfMinusOneIsNotANumber() { assertThat(Math.sqrt(-1), is(notANumber())); } } ```



Notice we are now using the Hamcrest library is matcher imported from our own custom Matchers class.


Notice 우리는 custom Matchers class 에서 importe된 matcher 인 Hamcrest library를 사용하게 됩니다.



Where next?

See FurtherResources.

--Tom White

저작자 표시 비영리 동일 조건 변경 허락
신고


Asynchronous Testing with Protractor’s ControlFlow


Protractor is an end-to-end testing framework for AngularJS applications that uses a real browser, just as a real user would. It is built on top of NodeJS and WebDriverJS and taps into the internals of Angular to know when Angular is done processing and updating bindings.



Protractor는 real user would와 마찬가지로 실제 브라우저를 사용하는 AngularJS 응용 프로그램의 end-to-end testing framework입니다. NodeJS 및 WebDriverJS 위에 구축되며 Angular의 내부를 tap해서 Angular가 바인딩 처리 및 업데이트를 완료 한 시점을 알 수 있습니다.


The joy of Protractorand WebDriverJS is that we can write our tests in a synchronous style, and still have the added benefits of asynchronous code. 


Protractor와 WebDriverJS의 강점은 동기식 스타일로 테스트를 작성할 수 있으며 비동기 코드의 부가적인 이점을 여전히 가지고 있다는 것입니다.

We are currently using Protractor for testing a Rails and Angular application that we’re developing here in the Detroit office. We were faced with a problem: “How do we write our own functions which are asynchronous but appear in the same synchronous style that Protractor tests are written in?” This is especially handy for performing REST requests for seeding data into the test database using something like the rails Hangar gem. 


우리는 현재 디트로이트 사무실에서 개발중인 Rails 및 Angular 응용 프로그램을 테스트하기 위해 Protractor를 사용하고 있습니다. "비동기식이지만 Protractor로 작성된 동기식으로 보이는 함수는 어떻게 작성합니까"  이것은 rails Hangar gem 같은 것을 사용해서 테스트 데이터베이스에 데이터를 넣기 위한 REST requests를 수행 할 때 특히 유용합니다. 


The ControlFlow


This required diving into the internals of how Protractor and WebDriverJS handle asynchrony. WebDriverJS uses an object called theControlFlow, which coordinates the scheduling and execution of commands operating on a queue. 


Any time an asynchronous command is invoked, it’s put in the queue where it will wait for all previous commands to complete prior to execution. The ControlFlow allows us to write code like this:


Protractor와 WebDriverJS가 어떻게 비동기를 처리하는지에 대해 좀 더 깊이 들어가겠습니다. WebDriverJS는 theControlFlow라는 객체를 사용합니다. 이 객체는 queue에서 작동하는 명령의 일정과 실행을 조정합니다.


비동기 명령이 호출 될 때마다 queue에 저장되어 실행 되기 전 모든 이전 명령들이 완료 될 때까지 대기합니다. ControlFlow를 사용하면 다음과 같은 코드를 작성할 수 있습니다.


driver.get(“http://www.google.com”);
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver');
driver.findElement(webdriver.By.name('btnG')).click();
driver.getTitle().then(function(title) {
  console.log(title);
});


That really performs in a synchronous manner such as this:

이것은 아래와 같이 동기화 방식으로 처리 됩니다.


driver.get(“http://www.google.com”).
    then(function() {
      return driver.findElement(webdriver.By.name('q'));
    }).
    then(function(q) {
      return q.sendKeys('webdriver');
    }).
    then(function() {
      return driver.findElement(webdriver.By.name('btnG'));
    }).
    then(function(btnG) {
      return btnG.click();
    }).
    then(function() {
      return driver.getTitle();
    }).
    then(function(title) {
      console.log(title);
    });


Behind the scenes of WebDriver, each call that interacts with the browser, such as get()findElement()sendKeys(), and click(), is being scheduled and pushed onto the WebDriver ControlFlow, allowing us to not have to worry about using .then() on the resulting promises (unless we specifically want the result returned by the call). 

WebDriver의 이면에서 get (), findElement (), sendKeys () 및 click ()과 같이 브라우저와 상호 작용하는 각 호출이 예약되고 WebDriver ControlFlow에 푸시되므로 resulting promises 에 대해 걱정할 필요가 없습니다 (호출에 의해 반환 된 결과가 특별히 필요하지 않는 한)


Using the WebDriverJS Promises



The ControlFlow queues functions based on promises. The following code exhibits how to take a callback based function and wrap it into WebDriver’s Promise API. We will be using the Restler NodeJS library.


ControlFlow 대기열 기능은 promises를 기반으로합니다. 아래 코드는 callback 기반 함수를 WebDriver의 Promise API로 래핑하는 방법을 보여줍니다. 우리는 Restler NodeJS 라이브러리를 사용할 것입니다.

To create a WebDriver/Protractor deferred using their promise API:

promise API를 사용하여 지연된 WebDriver / Protractor를 만들려면 :


deferred = protractor.promise.defer()


Then fullfill or reject the promise based on Restler’s events and return the deferred promise:


restler.postJson(url, requestData, options).once('success', function() {
  return deferred.fulfill();
}).once('error', function() {
  return deferred.reject();
}).once('fail', function() {
  return deferred.reject();
});
 
deferred.promise;


Pushing the Promise Onto the ControlFlow



To solve our problem of invoking a synchronous REST request, we have to interact with WebDriver’s ControlFlow. 

To get the instance of the ControlFlow that is shared with protractor:


synchronous REST request를 invoking하는 문제를 해결하려면 WebDriver의 ControlFlow와 상호 작용해야합니다.

Protractor와 공유되는 ControlFlow의 인스턴스를 얻으려면 :


var flow = browser.controlFlow()


Then we can use the ControlFlow’s execute() function, assuming we created a based on the above code that wraps restler’s callbacks and returns a WebDriverJS promise:


그런 다음 Restler의 콜백을 래핑하고 WebDriverJS 약속을 반환하는 위 코드를 기반으로 ControlFlow의 execute () 함수를 사용할 수 있다고 가정합니다.


flow.execute(restFunction)


Chaining Promises and Getting Results



The good news is that ControlFlow’s execute() function returns a new promise that will be fulfilled when our original promise is executed by the scheduler. We can use use the all() function, which returns a new promise once all of the control flow’s promises are fulfilled:

좋은 소식은 ControlFlow의 execute () 함수가 새 promise를 반환한다는 겁니다. 이렇게 함으로서 원래 약속이 스케줄러에 의해 실행될 때 수행 될 이 조건이 충족되게 됩니다. 모든 control flow의 promises가 충족 됐을 때 new promise 가 반환되는 all () 함수를 사용할 수 있습니다.


var allPromise = protractor.promise.all(flow.execute(restFunction1), flow.execute(restFunction2))



When allPromise is fulfilled, it will return an array of the results of all the promises passed to all() as arguments. 

allPromise가 수행되면 all ()에 전달 된 모든 promises의 결과 배열을 인수로 반환합니다.


Ideally the implementation of your helper functions would abstract the intermediary promises that are being passed to the ControlFlow and purely operate based upon the promises returned from the ControlFlow’s execute function.

이상적으로 helper 함수의 구현은 ControlFlow로 전달되는 intermediary promises을 abstract화하고 ControlFlow의 실행 함수에서 반환 된 promises를 기반으로 작동합니다.


저작자 표시 비영리 동일 조건 변경 허락
신고


Simple version of LED Light stand base for 3D crystal laser cube



I have Taj Mahal 3D crystal laser Cube.

You can get it from ebay also.





I found there are many stand bases for these kind of 3D crystal cube and it makes gorgeous view of it. like below.



So I've decided to develop it using Arduino.


The result is this.





This is the Source code.


/*

  For LED Light stand for 3D Crystal laser cube


  version : 0.4


  created 03 May 2017


  by Douglas Changsoo Park

*/


// Define Pins

#define RED1 3

#define GREEN1 4

#define BLUE1 5

#define RED2 6

#define GREEN2 7

#define BLUE2 8

#define delayTime 100


// define variables

int redValue1;

int greenValue1;

int blueValue1;

int redValue2;

int greenValue2;

int blueValue2;


void setup() {

  pinMode(RED1, OUTPUT);

  pinMode(GREEN1, OUTPUT);

  pinMode(BLUE1, OUTPUT);

  digitalWrite(RED1, HIGH);

  digitalWrite(GREEN1, HIGH);

  digitalWrite(BLUE1, HIGH);


  pinMode(RED2, OUTPUT);

  pinMode(GREEN2, OUTPUT);

  pinMode(BLUE2, OUTPUT);

  digitalWrite(RED2, HIGH);

  digitalWrite(GREEN2, HIGH);

  digitalWrite(BLUE2, HIGH);


  redValue1 = random(1, 255);

  greenValue1  = random(1, 255);

  blueValue1  = random(1, 255);

  redValue2 = random(1, 255);

  greenValue2  = random(1, 255);

  blueValue2  = random(1, 255);

}


void loop() {

  LEDLights(redValue1, greenValue1, blueValue1, redValue2, greenValue2, blueValue2);

  delay(delayTime * 4);

}


void LEDLights(int red1, int green1, int blue1, int red2, int green2, int blue2) {


  redValue1 = red1;

  greenValue1 = green1;

  blueValue1 = blue1;

  redValue2 = red2;

  greenValue2 = green2;

  blueValue2 = blue2;


  int redResult1 = randomValue(redValue1);

  int greenResult1 = randomValue(greenValue1);

  int blueResult1 = randomValue(blueValue1);


  int redResult2 = randomValue(redValue2);

  int greenResult2 = randomValue(greenValue2);

  int blueResult2 = randomValue(blueValue2);


  for (int i = 0; i < 25; i += 1) {

    analogWrite(RED1, redValue1 + redResult1);

    analogWrite(GREEN1, greenValue1 + greenResult1);

    analogWrite(BLUE1, blueValue1 + blueResult1);

    analogWrite(RED2, redValue2 + redResult2);

    analogWrite(GREEN2, greenValue2 + greenResult2);

    analogWrite(BLUE2, blueValue2 + blueResult2);


    redValue1 = redValue1 + redResult1;

    greenValue1 = greenValue1 + greenResult1;

    blueValue1 = blueValue1 + blueResult1;

    redValue2 = redValue2 + redResult2;

    greenValue2 = greenValue2 + greenResult2;

    blueValue2 = blueValue2 + blueResult2;


    delay(delayTime);

  }

}


int randomValue(int value) {

  int result;

  int minN;

  int maxN;


  int interval = random(1, 5);


  if (interval == 1) {

    minN = 26;

    maxN = 229;

  } else if (interval == 2) {

    minN = 51;

    maxN = 204;

  } else if (interval == 3) {

    minN = 76;

    maxN = 179;

  } else if (interval == 4) {

    minN = 101;

    maxN = 154;

  } else {

    minN = 126;

    maxN = 129;

  }


  if (value < minN) {

    result = interval;

  } else if (value > maxN) {

    result = -interval;

  } else {

    int randomVal = random(0, 1);

    if (randomVal == 0) {

      result = interval;

    } else {

      result = -interval;

    }

  }


  return result;

}




I wanted to make a combination and change of a more varied and softer color using random() in randomValue() function.


LEDLights() function will turn on and change the LED Light with the return value of the randomValue() function.


The loop() function will call the LED LIghts() function repeatedly every given time.


The components will be configured as below.





I've used Arduino Nano, 12V battery pack with 8 AAA batteries, 1 car charger adapter, small bread board and 2 RGB LEDs.


all parts are what I already have. 


It will cost about $ 15 for a new purchase.



Link to my project in hackster.


https://www.hackster.io/solkit/portable-led-light-stand-for-3d-crystal-laser-cube-5d8bd1







저작자 표시 비영리 동일 조건 변경 허락
신고

티스토리 툴바