Tempescope가 오픈소스라서 정보도 많이 풀려있고

어려운 프로젝트는 아닌것같습니다만 아두이노 초보자인 저에겐 

우여곡절이 많은 프로젝트네요

그래도 부딪히면서 배우는게 많아요 ㅋㅋ

제 스토리에는 그런 세세한 문제들까지 다 작성해놓으니 여러분은 즐거운 메이킹 하시길~!


기본적인 소스 모델은 @김보성 메이커님의 weather cube 프로젝트에 있는 소스인데요

김보성메이커님과 제가 쓰는 와이파이쉴드가 달라서 조금 수정을 했습니다. 


그리고 저는 네오픽셀 스트립을 사용하려고 했습니다. 

그 이유는 네오픽셀 스트립은 아두이노 출력 전압으로도 제어가 가능해서 

별도의 외부전원이 필요 없었거든요 



#include <Adafruit_CC3000.h>      // CC3000와이파이 쉴드 헤더파일
#include <Adafruit_CC3000_Server.h>
#include <ccspi.h>
#include <string.h>
#include <SPI.h>
#include <Adafruit_NeoPixel.h> // 네오픽셀 라이브러리
#define PIN 6 // 네오픽셀 할당 핀(Digital 6)
#define N_LEDS 30 // 사용 LED 개수

Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);

// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 2 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 7
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed but DI

#define WLAN_SSID "Dof" // cannot be longer than 32 characters!
#define WLAN_PASS "a07240724"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2

int Smog = 5; // smog ㅋㅋ 안개발생기
int WATER = 4; // 워터펌프
//int FOG = 8;

void setup() {
pinMode(Smog, OUTPUT);
pinMode(WATER, OUTPUT);
// pinMode(FOG, OUTPUT);
strip.begin(); // 네오픽셀 초기 값
strip.show(); // 네오픽셀 출력 함수
digitalWrite(Smog, LOW);
digitalWrite(WATER, LOW);
// digitalWrite(FOG, LOW);

// put your setup code here, to run once:
Serial.begin(115200);
Serial.println(F("Hello, CC3000!\n"));

displayDriverMode();

/* Initialise the module */
Serial.println(F("\nInitialising the CC3000 ..."));
if (!cc3000.begin())
{
Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
Error();
while(1);
}

uint16_t firmware = checkFirmwareVersion();
if (firmware < 0x113) {
Serial.println(F("Wrong firmware version!"));
Error();
for(;;);
}

displayMACAddress();

/* Delete any old connection data on the module */
Serial.println(F("\nDeleting old connection profiles"));
if (!cc3000.deleteProfiles()) {
Serial.println(F("Failed!"));
Error();
while(1);
}

/* Attempt to connect to an access point */
char *ssid = WLAN_SSID; /* Max 32 chars */
Serial.print(F("\nAttempting to connect to ")); Serial.println(ssid);

if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
Error();
while(1);
}

Serial.println(F("Connected!"));

/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}

/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}

}
int weather;

void loop() {
// put your main code here, to run repeatedly:
Data_Phasing();
delay(1500);
if(weather>0){
Effects();
delay(3600000);
}
}


/**************************************************************************/
/*!
@brief Displays the driver mode (tiny of normal), and the buffer
size if tiny mode is not being used

@note The buffer size and driver mode are defined in cc3000_common.h
*/
/**************************************************************************/
void displayDriverMode(void)
{
#ifdef CC3000_TINY_DRIVER
Serial.println(F("CC3000 is configure in 'Tiny' mode"));
#else
Serial.print(F("RX Buffer : "));
Serial.print(CC3000_RX_BUFFER_SIZE);
Serial.println(F(" bytes"));
Serial.print(F("TX Buffer : "));
Serial.print(CC3000_TX_BUFFER_SIZE);
Serial.println(F(" bytes"));
#endif
}

/**************************************************************************/
/*!
@brief Tries to read the CC3000's internal firmware patch ID
*/
/**************************************************************************/
uint16_t checkFirmwareVersion(void)
{
uint8_t major, minor;
uint16_t version;

#ifndef CC3000_TINY_DRIVER
if(!cc3000.getFirmwareVersion(&major, &minor))
{
Serial.println(F("Unable to retrieve the firmware version!\r\n"));
Error();
version = 0;
}
else
{
Serial.print(F("Firmware V. : "));
Serial.print(major); Serial.print(F(".")); Serial.println(minor);
version = major; version <<= 8; version |= minor;
}
#endif
return version;
}

/**************************************************************************/
/*!
@brief Tries to read the 6-byte MAC address of the CC3000 module
*/
/**************************************************************************/
void displayMACAddress(void)
{
uint8_t macAddress[6];

if(!cc3000.getMacAddress(macAddress))
{
Serial.println(F("Unable to retrieve MAC Address!\r\n"));
Error();
}
else
{
Serial.print(F("MAC Address : "));
cc3000.printHex((byte*)&macAddress, 6);
}
}


/**************************************************************************/
/*!
@brief Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
Error();
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}

// What page to grab!
#define WEBSITE "api.openweathermap.org"
#define WEBPAGE "/data/2.5/weather?q=anyang,kr&mode=xml&appid=1a99de57fbb2158344786171f74fbe72"
uint32_t ip;

String currentLine = "";
String weatherString = "";
boolean readingWeather = false;

void Data_Phasing(){
ip = 0;
// Try looking up the website's IP address
Serial.print(WEBSITE); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
Error();
}
delay(500);
}

Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
if (www.connected()) {
www.fastrprint(F("GET "));
www.fastrprint(WEBPAGE);
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
Error();
return;
}

Serial.println(F("-------------------------------------"));

/* Read data until either the connection is closed, or the idle timeout is reached. */
unsigned long lastRead = millis();
currentLine = "";
while (www.connected()) {
while (www.available()) {
char inChar = www.read();
Serial.print(inChar);
currentLine += inChar;

if (inChar == '\n') {
//Serial.print("clientReadLine = ");
//Serial.println(currentLine);
currentLine = "";
break;
}

if ( currentLine.endsWith("<weather number=")){
//현재 스트링이 "<weather number="로 끝났다면 날씨 코드를 받을 준비를 한다.
readingWeather = true;
weatherString = "";
Serial.println("\n--- READ start");
}

if (readingWeather) {
if (inChar != 'v') { //다음 전송될 문자가 'v'가 아니라면 계속 날씨 데이터(코드)를 받는다.
weatherString += inChar;
Serial.println("\n--- add");
} else { //다음 전송된 문자가 'v'라면 날씨 데이터(코드)를 출력한다.
readingWeather = false;
weather = getInt(weatherString);
Serial.println("\n--- READ end");
Serial.println(weather);
www.close();
break;
}
}
}
}
Serial.println(F("-------------------------------------"));
}

int temp = 0;

int getInt(String input){ //String데이터를 intger형으로 변환하는 함수
temp=0;
int i = 2;
while(input[i] != '"'){
i++;
}
input = input.substring(2,i);
char carray[20];
//Serial.println(input);
input.toCharArray(carray, sizeof(carray));
//Serial.println(carray);
temp = atoi(carray);
//Serial.println(temp);
return temp;
}

void Effects(){
Serial.print("EFFECT: ");
Serial.println(weather);
if(weather>=200 && weather<300 || weather==781){ //Group 2xx: Thunderstorm
// 781: tornado
thunder();
}else if(weather>=300 && weather<400){ //Group 3xx: Drizzle
rainy();
}else if(weather>=500 && weather<600){ //Group 5xx: Rain
rainy();
}else if(weather>=600 && weather<700){ //Group 6xx: Snow
snowy();
}else if(weather>=702 && weather<800){ //Group 7xx: Atmosphere
cloudy();
}else if(weather==800 || weather==701){ //Group 800: Clear
// 701: mist
sunny();
}else if(weather>800 && weather<800){ //Group 80x: Clouds
cloudy();
}else if(weather>=900 && weather<910){ //Group 90x: Extreme
thunder();
}else if(weather>=910 && weather<1000){ //Group 9xx: Additional
if(weather>=957 && weather<960)
cloudy();
else if(weather>=960 && weather<963)
thunder();
else
sunny();
}
}

void sunny(){
Serial.println("sunny");
Fine_LED();
digitalWrite(Smog, LOW);
digitalWrite(WATER, LOW);
// digitalWrite(FOG, LOW);
}

void cloudy(){
Serial.println("cloudy");
Cloudy_LED();
digitalWrite(Smog, HIGH);
digitalWrite(WATER, LOW);
// digitalWrite(FOG, HIGH);
}

void rainy(){
Serial.println("rainy");
Light_Rainy_LED();
digitalWrite(Smog, HIGH);
digitalWrite(WATER, HIGH);
// digitalWrite(FOG, HIGH);
}

void thunder(){
Serial.println("thunder");
Lightening_LED();
digitalWrite(Smog, HIGH);
digitalWrite(WATER, HIGH);
// digitalWrite(FOG, HIGH);
}

void snowy(){
Serial.println("snowy");
Snowy_LED();
digitalWrite(Smog, HIGH);
digitalWrite(WATER, HIGH);
// digitalWrite(FOG, HIGH);
}

void Error(){
Serial.println("ERROR");

digitalWrite(Smog, LOW);
digitalWrite(WATER, LOW);
// digitalWrite(FOG, LOW);
}
void Fine_LED() // '맑은 날' LED 출력
{
int i;
for(i=0;i<201;i++)
{
LED_ON(strip.Color(255,i,0));
}
for(i=0;i<47;i++)
{
LED_ON(strip.Color(255,200,i));
}
for(i=0;i<56;i++)
{
LED_ON(strip.Color(255,200+i,46));
}
for(i=0;i<210;i++)
{
LED_ON(strip.Color(255,255,46+i));
}
for(i=0;i<256;i++)
{
LED_ON(strip.Color(255,255-i,255-i));
}
}

void Cloudy_LED() // '구름 낀 날' LED 출력
{
int i,j;
for(j=30;j<255;j++)
{
LED_ON(strip.Color(j, j, j));
}
for(j=255;j>30;j--)
{
LED_ON(strip.Color(j, j, j));

}
delay(3000);
}

void Snowy_LED() // '눈 오는 날' LED 출력
{
LED_ON(strip.Color(150, 150, 150));
delay(2000);
LED_ON(strip.Color(0,0,0));
delay(10);
LED_ON(strip.Color(150, 150, 150));
}
void Light_Rainy_LED() // '약한 비' LED 출력
{
int i;
for(i=0;i<201;i++)
{
LED_ON(strip.Color(0,234-i,234-i));
}
for(i=0;i<201;i++)
{
LED_ON(strip.Color(0,34+i,34+i));
}
}

void Lightening_LED() // '뇌우' LED 출력
{
int i,j,k;
for(i=0;i<15;i++)
{
LED_ON(strip.Color(80, 80, 250));
delay(10);
LED_ON(strip.Color(0, 0, 0));
delay(5);
}
for(i=0;i<5;i++)
{
LED_ON(strip.Color(80, 80, 250));
delay(500);
LED_ON(strip.Color(0, 0, 0));
delay(100);
}
for(i=0;i<8;i++)
{
LED_ON(strip.Color(80, 80, 250));
delay(1000);
LED_ON(strip.Color(0, 0, 0));
delay(50);
}
}

void LED_ON(uint32_t c) // String LED 출력 함수
{
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
}
}



























































































































































































































































































































































































































































































 제가 작성한 코드입니다. 

#define WLAN_SSID       "Dof"        // cannot be longer than 32 characters!
#define WLAN_PASS "a07240724"

이 부분이 이제 WIFI AP를 설정해주는 부분입니다.

SSID 에 와이파이 ID를 그 밑줄인 PASS에 비밀번호를 써주시고 업로드를 해주시면 됩니다. 

그리고 쉴드마다 사용하는 핀번호가 서로 다르니 이점 유의하시고 코드를 수정해주세요 


정상적으로 동작을 하게 되면 

아이피 뿌리구 맥어드레스 막나오고 그러다가 날씨 데이터를 파싱해옵니다

--- READ start


--- add

"

--- add

7

--- add

2

--- add

1

--- add

"

--- add

 

--- add

v

--- READ end

721

-------------------------------------

EFFECT: 721

cloudy


이렇게 날씨 데이터가 나옵니다.
그럼 날씨에 맞게 효과(이펙트)가 작동이 되겠죠?

근데 제가 작성한 코드를 업로드시키면 마지막에 저 날씨값을 받아오질 못합니다... 
원인은 정확하지 않지만요 제 생각에는 
네오픽셀스트립이 보통 루프안에서 동작을 시키는데 루프안에는 날씨 데이터를 받아오는 코드가 있어서
루프를 사용하지 못해요 ( 아두이노는 멀티스레드 지원이 안되어서 루프는 1개만 사용가능 ) 
그래서 루프 밖에서 외부함수로 for문을 이용해서 동작시키는데 이 때 인터럽트가 발생해서 루프안에서 데이터를  받아오는 코드가 동작을 안하는 것 같습니다... 


우선 너무 시간이 지체되었으니 내일 RGB LED strip 을 사서 동작시켜봐야겠어요...

댓글 0

Tempescope project

#5. WIFI쉴드와 네오픽셀은 물과기름?

by 과일대장

MADE BY