wireless:wifi [2013/01/15 22:08] boxtec updated |
wireless:wifi [2013/02/02 15:45] (current) boxtec added article links |
| | | |
| void sendCMD(char cmd[], int _delay) { | | void sendCMD(char cmd[], int _delay) { |
- | long _wait = 0; | |
| mySP.println(cmd); | | mySP.println(cmd); |
- | delay(1); | + | delay(_delay); |
| } | | } |
| | | |
| Unser kleines Projekt umfasst: | | Unser kleines Projekt umfasst: |
| | | |
- | - Arduino Uno Board | + | - [[http://shop.boxtec.ch/arduino-p-40155.html|Arduino Uno Board]] |
- | - XBee Shield | + | - [[http://shop.boxtec.ch/xbee-shield-enhanced-xbee-breakdout-arduino-p-40296.html|XBee Shield]] |
- | - WiFly | + | - [[http://shop.boxtec.ch/wifly-module-p-40411.html|RN-XV WiFly Modul]] |
- | - DHT22 | + | - [[http://shop.boxtec.ch/digital-humiditytemperature-sensor-dht22-rht03-p-40371.html|DHT22]] |
- | - 2x DS18B20 | + | - [[http://shop.boxtec.ch/ds18b20-1wire-digital-thermometer-p-40366.html|2x DS18B20]] |
- | - Protonly | + | - [[http://shop.boxtec.ch/protonly-protoshield-p-41152.html|Protonly Shield]] |
- | - PIR Sensor | + | - [[http://shop.boxtec.ch/tiny-motion-sensor-module-p-40293.html|Tiny PIR Sensor]] |
- | - 12V LED Streifen weiss ca. 150cm | + | - [[http://shop.boxtec.ch/strip-352860m-warm-white-p-40837.html|12V LED Streifen weiss ca. 150cm]] |
- | - MOSFET RFD1405 | + | - [[http://shop.boxtec.ch/advanced_search_result.php?keywords=mosfet|MOSFET RFD1405 oder anderes N-Kanal Modell]] |
- | - Solid State Relay zur Lüftersteuerung | + | - [[http://shop.boxtec.ch/solid-state-relay-10da-p-40459.html|Solid State Relay zur Lüftersteuerung]] |
- | - einige Widerstände | + | - [[http://shop.boxtec.ch/resistor-p-40545.html|einige Widerstände]] |
- | - 12V Netzadapter | + | - [[http://shop.boxtec.ch/advanced_search_result.php?keywords=ac+adapter+12v|12V Netzadapter]] |
- | - wasserfestes Gehäuse | + | - [[http://shop.boxtec.ch/waterproof-enclosure-158x90x60mm-p-41154.html|wasserfestes Gehäuse]] |
- | - ein blaues LED mit Vorwiderstand für I-Effekt und weil wir es können und noch PWM I/O frei hatten :-) | + | - [[http://shop.boxtec.ch/quick-lock-splice-wire-connector-18awg-p-41043.html|Quick Lock Wire Splice]] |
| + | - [[http://shop.boxtec.ch/starter-p-40898.html|ein blaues LED]] mit Vorwiderstand für I-Effekt und weil wir es können und noch PWM I/O frei hatten :-) |
| + | - Etwas [[http://shop.boxtec.ch/ribbon-cable-wire-p-40437.html|Flachbandkabel]] und [[http://shop.boxtec.ch/solder-leaded-tube-p-40564.html|Lötzinn]] |
| + | - Ca. 1m Netzkabel 3-adrig (min. 1mm2) sowie eine 230V Stecker und 230V Buchse |
| | | |
| + | ---- |
| + | === Das fertige Projekt === |
| + | {{:wireless:wifly-project1.jpg?644x484|Gehäuse geschlossen}} |
| + | |
| + | {{:wireless:wifly-project2.jpg?644x484|Gehäuse innen}} |
| + | |
| + | === Der Arduino Sketch === |
| + | <code c> |
| + | // Copyright (c) 2002-2012 boxtec internet appliances <playground@boxtec.ch> |
| + | // |
| + | // All rights reserved. |
| + | // |
| + | // Redistribution and use in source and binary forms, with or without |
| + | // modification, are permitted provided that the following conditions |
| + | // are met: |
| + | // 1. Redistributions of source code must retain the above copyright |
| + | // notice, this list of conditions and the following disclaimer. |
| + | // 2. Redistributions in binary form must reproduce the above copyright |
| + | // notice, this list of conditions and the following disclaimer in the |
| + | // documentation and/or other materials provided with the distribution. |
| + | // 3. The name of the author may not be used to endorse or promote products |
| + | // derived from this software without specific prior written permission. |
| + | // |
| + | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| + | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
| + | // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
| + | // THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| + | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| + | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| + | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| + | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| + | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| + | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + | // |
| + | // -------------------------------------------------------------------------- |
| + | // $Id: wifi_sensor.ino,v 1.10 2013-01-01 10:21:34 obiwan Exp $ |
| + | // -------------------------------------------------------------------------- |
| + | // |
| + | // Written for Arduino IDE 1.0 |
| + | // |
| + | // LEDs: |
| + | // Power (fade) |
| + | // SSR State |
| + | // Light State |
| + | // Motion Detect |
| + | // |
| + | // PINS: |
| + | // PIR : 3 |
| + | // LIGHT : 5 |
| + | // LED-PWR: 6 |
| + | // SSR : 11 |
| + | // DHT : 12 |
| + | // Onewire: 13 |
| + | // |
| + | |
| + | |
| + | #include <AltSoftSerial.h> |
| + | // TX: 9, RX: 8, Unusable PWM: 10 |
| + | // see http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html |
| + | #include <OneWire.h> |
| + | #include <DallasTemperature.h> |
| + | #include <dht.h> |
| + | |
| + | // DEBUGGING (enable to debug) |
| + | //#define SDBG |
| + | |
| + | #define BUF_SIZE 255 |
| + | #define ESCAPE_CHAR '*' |
| + | #define ONE_WIRE_BUS 13 |
| + | #define DHT_PIN 12 |
| + | #define SSR_PIN 11 |
| + | #define PIR_PIN 3 |
| + | #define LIGHT_PIN 5 |
| + | #define LED0_PIN 6 |
| + | #define CMD_DELAY 540 |
| + | #define ESC_DELAY 685 |
| + | #define PIR_DELAY 50000 |
| + | #define LOOP_IX_MAX 60 |
| + | #define INOUT_DIFF 3 |
| + | #define LIGHT_INCR 16 |
| + | #define LIGHT_DECR 5 |
| + | |
| + | #define TEMPERATURE_PRECISION 9 |
| + | #define TEMPERATURE_REFRESH 5000 |
| + | #define REGULATOR_REFRESH 6000 |
| + | #define LED_REFRESH 75 |
| + | |
| + | int buffer_pos = 0; |
| + | byte led0_pwm = 0; |
| + | int led0_pwm_incr = 50; |
| + | char open_cmd[6] = "OPEN"; |
| + | char close_cmd[6] = "CLOS"; |
| + | float cur_temp; |
| + | float cur_hyg; |
| + | float temperature0; |
| + | float temperature1; |
| + | float target_temp = 31; |
| + | float target_hyg = 48; |
| + | volatile long pir_timer = 0; |
| + | volatile int light_level = 0; |
| + | long loop_start = 0; |
| + | long loop_duration_avg = 500; |
| + | int loop_ix = 1; |
| + | long loop_sum = 10000000; |
| + | int pwm_incr = 50; |
| + | |
| + | OneWire oneWire(ONE_WIRE_BUS); |
| + | DallasTemperature sensors(&oneWire); |
| + | DeviceAddress outside0Temp, outside1Temp; |
| + | AltSoftSerial mySP; |
| + | dht DHT; |
| + | |
| + | |
| + | // |
| + | // SETUP |
| + | // |
| + | void setup() { |
| + | #ifdef SDBG |
| + | Serial.begin(57600); |
| + | while (!Serial) { |
| + | ; // wait for serial port to connect. Needed for Leonardo only |
| + | } |
| + | #endif |
| + | |
| + | analogWrite(LED0_PIN, 200); |
| + | pinMode(SSR_PIN, OUTPUT); |
| + | pinMode(PIR_PIN, INPUT); |
| + | analogWrite(LIGHT_PIN, 8); |
| + | digitalWrite(SSR_PIN, LOW); |
| + | mySP.begin(9600); |
| + | delay(CMD_DELAY); |
| + | sendESC("$$$", ESC_DELAY); |
| + | sendCMD("reboot",1600); |
| + | sendCMD("factory RESET", 1800); |
| + | readData(); |
| + | sendESC("$$$", ESC_DELAY); |
| + | sendCMD("set wlan rate 0", CMD_DELAY); |
| + | sendCMD("set wlan ssid IHRE-WLAN-ID", CMD_DELAY); |
| + | sendCMD("set wlan phrase Ihr-WLAN-Passw0rt", CMD_DELAY); |
| + | sendCMD("set ip dhcp 1", CMD_DELAY); |
| + | sendCMD("set comm idletimer 1", CMD_DELAY); |
| + | sendCMD("set comm remote 0", CMD_DELAY); |
| + | sendCMD("set comm match 13", CMD_DELAY); |
| + | sendCMD("set ip host 192.68.1.100", CMD_DELAY); |
| + | sendCMD("set ip remote 8000", CMD_DELAY); |
| + | sendCMD("join IHRE-WLAN-ID", 6000); |
| + | readData(); |
| + | sendCMD("exit",100); |
| + | |
| + | sensors.begin(); |
| + | // set the resolution to 12 bit |
| + | sensors.setResolution(outside0Temp, TEMPERATURE_PRECISION); |
| + | sensors.setResolution(outside1Temp, TEMPERATURE_PRECISION); |
| + | |
| + | #ifdef SDBG |
| + | Serial.print("Status PIR Sensor: "); |
| + | Serial.println(digitalRead(PIR_PIN)); |
| + | |
| + | Serial.print("Device 0 Resolution: "); |
| + | Serial.print(sensors.getResolution(outside0Temp), DEC); |
| + | Serial.println(); |
| + | |
| + | Serial.print("Device 1 Resolution: "); |
| + | Serial.print(sensors.getResolution(outside1Temp), DEC); |
| + | Serial.println(); |
| + | |
| + | Serial.print("Found "); |
| + | Serial.print(sensors.getDeviceCount(), DEC); |
| + | Serial.println(" devices."); |
| + | |
| + | // report parasite power requirements |
| + | Serial.print("Parasite power is: "); |
| + | if (sensors.isParasitePowerMode()) Serial.println("ON"); |
| + | else Serial.println("OFF"); |
| + | |
| + | if (!sensors.getAddress(outside0Temp, 0)) Serial.println("Unable to find address for Device 0"); |
| + | Serial.print("Device 0 Address: "); |
| + | printAddress(outside0Temp); |
| + | Serial.println(); |
| + | if (!sensors.getAddress(outside1Temp, 1)) Serial.println("Unable to find address for Device 1"); |
| + | Serial.print("Device 1 Address: "); |
| + | printAddress(outside1Temp); |
| + | Serial.println(); |
| + | #else |
| + | // obviously needed to initialise sensors |
| + | sensors.getAddress(outside0Temp, 0); |
| + | sensors.getAddress(outside1Temp, 1); |
| + | #endif |
| + | sensors.requestTemperatures(); |
| + | DHT.read22(DHT_PIN); |
| + | attachInterrupt(1, pir_detect, RISING); |
| + | analogWrite(LED0_PIN, 0); |
| + | analogWrite(LIGHT_PIN, 0); |
| + | } |
| + | |
| + | // |
| + | // LOOP |
| + | // |
| + | void loop() { |
| + | mainperf(true); |
| + | readData(); |
| + | delayMicroseconds(5); |
| + | if ( millis() % LED_REFRESH == 0 ) { |
| + | led_refresh(); |
| + | light_dim(); |
| + | } |
| + | if ( millis() % TEMPERATURE_REFRESH == 0 ) { |
| + | updateValues(); |
| + | } |
| + | if ( millis() % REGULATOR_REFRESH == 0 ) { |
| + | regulator(); |
| + | } |
| + | mainperf(false); |
| + | } |
| + | |
| + | void sendESC(char esc[], int _delay) { |
| + | #ifdef SDBG1 |
| + | Serial.print("ESC: "); |
| + | Serial.println(esc); |
| + | #endif |
| + | readData(); |
| + | mySP.print(esc); |
| + | delay(_delay); |
| + | readData(); |
| + | } |
| + | |
| + | void sendCMD(char cmd[], int _delay) { |
| + | long _wait = 0; |
| + | readData(); |
| + | #ifdef SDBG |
| + | Serial.print("CMD: "); |
| + | Serial.println(cmd); |
| + | #endif |
| + | mySP.println(cmd); |
| + | delay(1); |
| + | readData(); |
| + | while ( _wait < _delay ) { |
| + | readData(); |
| + | delay(10); |
| + | _wait += 10; |
| + | } |
| + | readData(); |
| + | } |
| + | |
| + | // |
| + | // update global temp/hyg values |
| + | // |
| + | void updateValues() { |
| + | sensors.requestTemperatures(); |
| + | DHT.read22(DHT_PIN); |
| + | cur_temp = DHT.temperature; |
| + | cur_hyg = DHT.humidity; |
| + | temperature0 = sensors.getTempC(outside0Temp); |
| + | temperature1 = sensors.getTempC(outside1Temp); |
| + | } |
| + | |
| + | // |
| + | // send data to network clients |
| + | // |
| + | void sendData() { |
| + | char tpl[] = "%s:%s:%s:%s:%s:%s:%d:%d:%d"; |
| + | char out_string[64]; |
| + | char temp1[6]; |
| + | char temp2[6]; |
| + | char temp3[6]; |
| + | char hyg1[6]; |
| + | char c_target_temp[6]; |
| + | char c_target_hyg[6]; |
| + | unsigned int pir_status; |
| + | dtostrf(temperature0, 2, 1, temp1); |
| + | dtostrf(temperature1, 2, 1, temp2); |
| + | dtostrf(cur_temp, 2, 1, temp3); |
| + | dtostrf(cur_hyg, 2, 1, hyg1); |
| + | dtostrf(target_temp, 2, 1, c_target_temp); |
| + | dtostrf(target_hyg, 2, 1, c_target_hyg); |
| + | if (millis() - PIR_DELAY < pir_timer) { |
| + | pir_status = (millis() - pir_timer) / 1000; |
| + | if ( pir_status == 0 ) { |
| + | pir_status = 1; |
| + | } |
| + | } |
| + | else { |
| + | pir_status = 0; |
| + | } |
| + | sprintf(out_string, tpl, temp1, temp2, temp3, hyg1, c_target_temp, c_target_hyg, bitRead(PORTD,LIGHT_PIN), bitRead(PORTB,3), pir_status); |
| + | #ifdef SBDG |
| + | Serial.print("OUT: "); |
| + | Serial.println(out_string); |
| + | #endif |
| + | mySP.println(out_string); |
| + | } |
| + | |
| + | // |
| + | // read data from entwork |
| + | // |
| + | void readData() { |
| + | int buffer_pos = 0; |
| + | int escape_buffer_pos = 0; |
| + | boolean escape_detected = false; |
| + | char escape_buffer[8] = ""; |
| + | char input_buffer[BUF_SIZE] = ""; |
| + | |
| + | if ( mySP.available() ){ |
| + | while (mySP.available() > 0) { |
| + | char cin = mySP.read(); |
| + | // ESC starts |
| + | if ( cin == ESCAPE_CHAR && escape_buffer_pos == 0 ) { |
| + | escape_detected = true; |
| + | } |
| + | // ESC ends |
| + | else if ( cin == ESCAPE_CHAR && escape_buffer_pos > 0 ) { |
| + | delay(1); |
| + | // Send Data over network |
| + | sendData(); |
| + | #ifdef SDBG |
| + | Serial.print("Esc_buf: "); |
| + | Serial.println(escape_buffer); |
| + | #endif |
| + | escape_detected = false; |
| + | escape_buffer_pos = 0; |
| + | buffer_pos = 0; |
| + | } |
| + | // Escape sequence detected |
| + | else if ( escape_detected && open_cmd[escape_buffer_pos] == cin || |
| + | escape_detected && close_cmd[escape_buffer_pos] == cin ) { |
| + | escape_buffer[escape_buffer_pos] = cin; |
| + | escape_buffer_pos++; |
| + | } |
| + | // incoming data elsewise: |
| + | else { |
| + | input_buffer[buffer_pos] = cin; |
| + | buffer_pos++; |
| + | } |
| + | delayMicroseconds(1500); |
| + | } |
| + | #ifdef SDBG |
| + | Serial.print("IN: "); |
| + | Serial.println(input_buffer); |
| + | #endif |
| + | if ( input_buffer[0] == 'H' ) { |
| + | target_hyg = input_buffer[1]; |
| + | #ifdef SDBG |
| + | Serial.println("Set H Threshold to:"); |
| + | Serial.println(target_hyg); |
| + | #endif |
| + | } |
| + | else if ( input_buffer[0] == 'T' ) { |
| + | target_temp = input_buffer[1]; |
| + | #ifdef SDBG |
| + | Serial.println("Set T Threshold to:"); |
| + | Serial.println(target_temp); |
| + | #endif |
| + | } |
| + | |
| + | delay(0); |
| + | } |
| + | else { |
| + | delay(0); |
| + | } |
| + | } |
| + | |
| + | // |
| + | // regulate hyg and possibly temp with a fan |
| + | // |
| + | void regulator() { |
| + | // a PIR timer is running: |
| + | if (millis() - PIR_DELAY < pir_timer) { |
| + | digitalWrite(SSR_PIN, HIGH); |
| + | digitalWrite(LIGHT_PIN, HIGH); |
| + | } |
| + | else if (( cur_temp < target_temp ) && ( cur_hyg < target_hyg )) { |
| + | digitalWrite(SSR_PIN, LOW); |
| + | digitalWrite(LIGHT_PIN, LOW); |
| + | } |
| + | else if (( (cur_temp > target_temp) && (cur_temp > temperature0 + INOUT_DIFF) ) || ( cur_hyg > target_hyg )) { |
| + | digitalWrite(SSR_PIN, HIGH); |
| + | } |
| + | #ifdef SDBG |
| + | Serial.println("Regulator:"); |
| + | Serial.println(DHT.temperature); |
| + | Serial.println(DHT.humidity); |
| + | Serial.print("SSR_PIN, LIGHT_PIN: "); |
| + | Serial.print(bitRead(PORTB,3)); |
| + | Serial.print(" - "); |
| + | Serial.println(light_level); |
| + | if (millis() - PIR_DELAY < pir_timer) { |
| + | Serial.print("PIR Timeout in: "); |
| + | Serial.print((PIR_DELAY - (millis() - pir_timer)) / 1000); |
| + | Serial.println("sec"); |
| + | } |
| + | Serial.print("Avg. loop duration: "); |
| + | Serial.println(loop_duration_avg); |
| + | Serial.print("PWM Incr: "); |
| + | Serial.println(pwm_incr); |
| + | #endif |
| + | } |
| + | |
| + | // dim lights in and out |
| + | void light_dim() { |
| + | // a PIR timer is running: |
| + | if (millis() - PIR_DELAY < pir_timer) { |
| + | if (light_level + LIGHT_INCR < 255) { |
| + | light_level += LIGHT_INCR; |
| + | #ifdef SDBG |
| + | Serial.print("Increasing light:"); |
| + | Serial.println(light_level); |
| + | #endif |
| + | } |
| + | else if (light_level < 255) { |
| + | light_level = 255; |
| + | #ifdef SDBG |
| + | Serial.print("Maxing light:"); |
| + | Serial.println(light_level); |
| + | #endif |
| + | } |
| + | analogWrite(LIGHT_PIN, light_level); |
| + | } |
| + | else if ( (millis() - PIR_DELAY > pir_timer) && ( light_level > 0 ) ) { |
| + | if ( light_level - LIGHT_DECR >= 0 ) { |
| + | light_level -= LIGHT_DECR; |
| + | #ifdef SDBG |
| + | Serial.print("Decreasing light:"); |
| + | Serial.println(light_level); |
| + | #endif |
| + | } |
| + | else { |
| + | #ifdef SDBG |
| + | Serial.println("Light = 0 "); |
| + | #endif |
| + | light_level = 0; |
| + | } |
| + | analogWrite(LIGHT_PIN, light_level); |
| + | } |
| + | } |
| + | |
| + | void led_refresh() { |
| + | pwm_incr = loop_duration_avg / 25; |
| + | if (led0_pwm + led0_pwm_incr > 255) { |
| + | led0_pwm_incr = - pwm_incr; |
| + | } |
| + | else if (led0_pwm + led0_pwm_incr < 0) { |
| + | led0_pwm_incr = pwm_incr; |
| + | } |
| + | led0_pwm += led0_pwm_incr; |
| + | analogWrite(LED0_PIN, led0_pwm); |
| + | |
| + | } |
| + | |
| + | // check PIR sensor |
| + | void pir_detect() { |
| + | #ifdef SDBG |
| + | Serial.print("PIR: "); |
| + | Serial.println(digitalRead(PIR_PIN)); |
| + | #endif |
| + | pir_timer = millis(); |
| + | } |
| + | |
| + | // function to print a device address |
| + | void printAddress(DeviceAddress deviceAddress) |
| + | { |
| + | for (uint8_t i = 0; i < 8; i++) |
| + | { |
| + | if (deviceAddress[i] < 16) Serial.print("0"); |
| + | Serial.print(deviceAddress[i], HEX); |
| + | } |
| + | } |
| + | |
| + | // function to print a device's resolution |
| + | void printResolution(DeviceAddress deviceAddress) |
| + | { |
| + | Serial.print("Resolution: "); |
| + | Serial.print(sensors.getResolution(deviceAddress)); |
| + | Serial.println(); |
| + | } |
| + | |
| + | // function to print the temperature for a device |
| + | void printTemperature(DeviceAddress deviceAddress) |
| + | { |
| + | float tempC = sensors.getTempC(deviceAddress); |
| + | Serial.print("Temp C: "); |
| + | Serial.print(tempC); |
| + | Serial.print(" Temp F: "); |
| + | Serial.print(DallasTemperature::toFahrenheit(tempC)); |
| + | } |
| + | |
| + | // main function to print information about a device |
| + | void printData(DeviceAddress deviceAddress) |
| + | { |
| + | Serial.print("Device Address: "); |
| + | printAddress(deviceAddress); |
| + | Serial.print(" "); |
| + | printTemperature(deviceAddress); |
| + | Serial.println(); |
| + | } |
| + | |
| + | // measure loop performance and adjust PWM frequency accodingly |
| + | void mainperf(boolean start) { |
| + | int loop_duration; |
| + | if (start == true) { |
| + | loop_start = micros(); |
| + | } |
| + | else { |
| + | loop_duration = micros() - loop_start; |
| + | if (loop_ix >= LOOP_IX_MAX) { |
| + | loop_sum = loop_duration_avg*2; |
| + | loop_ix = 2; |
| + | } |
| + | else { |
| + | loop_duration_avg = loop_sum / loop_ix; |
| + | loop_sum += loop_duration; |
| + | loop_ix += 1; |
| + | } |
| + | } |
| + | |
| + | } |
| + | </code> |
| | | |
| | | |