Browse Source

Weather Report on a 5x10 LED-Matrix Arduino/WiFi/PHP

Custom font (5px)
RedFly-Shield (WiFi)
Pixel data generated with PHP
mcj201 9 years ago
parent
commit
00075ca929
6 changed files with 295 additions and 0 deletions
  1. BIN
      5by5.ttf
  2. 214 0
      5x10_led_scrolltext.ino
  3. 6 0
      data.txt
  4. BIN
      img.png
  5. 2 0
      index.php
  6. 73 0
      scroll.php

BIN
5by5.ttf


+ 214 - 0
5x10_led_scrolltext.ino

@@ -0,0 +1,214 @@
+#include <digitalWriteFast.h>
+#include <RedFly.h>
+#include <RedFlyServer.h>
+
+
+byte ip[]      = { 192,168,  0, 10 }; //ip from shield (server)
+byte netmask[] = { 255,255,255,  0 }; //netmask
+byte server[]  = { 192,168,  0,  2 }; //i.e. Raspberry Pi
+
+uint8_t http=INVALID_SOCKET; //socket handle
+uint16_t http_len=0; //receive len
+char http_buf[1024];  //receive buffer
+
+//debug output functions (9600 Baud, 8N2)
+//Leonardo boards use USB for communication, so we dont need to disable the RedFly
+void debugout(char *s)
+{
+#if defined(__AVR_ATmega32U4__)
+  Serial.print(s);
+#else
+  RedFly.disable();
+  Serial.print(s);
+  RedFly.enable();
+#endif
+}
+
+void debugoutln(char *s)
+{
+#if defined(__AVR_ATmega32U4__)
+  Serial.println(s);
+#else
+  RedFly.disable();
+  Serial.println(s);
+  RedFly.enable();
+#endif
+}
+
+
+void setup()
+{
+  for(int i=4; i<20; i++) pinMode(i, OUTPUT);
+  digitalWrite(15, 1);
+  digitalWrite(13, 1);
+  uint8_t ret;
+
+#if defined(__AVR_ATmega32U4__) //Leonardo boards use USB for communication
+  Serial.begin(9600); //init serial port and set baudrate
+  while(!Serial); //wait for serial port to connect (needed for Leonardo only)
+#endif
+  digitalWrite(12, 1);
+  digitalWrite(11, 1);
+  //init the WiFi module on the shield
+  // ret = RedFly.init(br, pwr) //br=9600|19200|38400|57600|115200|200000|230400, pwr=LOW_POWER|MED_POWER|HIGH_POWER
+  // ret = RedFly.init(pwr) //9600 baud, pwr=LOW_POWER|MED_POWER|HIGH_POWER
+  // ret = RedFly.init() //9600 baud, HIGH_POWER
+  ret = RedFly.init();
+  if(ret)
+  {
+    debugoutln("INIT ERR"); //there are problems with the communication between the Arduino and the RedFly
+  }
+  else
+  {
+    digitalWrite(10, 1);
+    //scan for wireless networks (must be run before join command)
+    RedFly.scan();
+
+    //join network
+    // ret = join("wlan-ssid", "wlan-passw", INFRASTRUCTURE or IBSS_JOINER or IBSS_CREATOR, chn, authmode) //join infrastructure or ad-hoc network, or create ad-hoc network
+    // ret = join("wlan-ssid", "wlan-passw", IBSS_CREATOR, chn) //create ad-hoc network with password, channel 1-14
+    // ret = join("wlan-ssid", IBSS_CREATOR, chn) //create ad-hoc network, channel 1-14
+    // ret = join("wlan-ssid", "wlan-passw", INFRASTRUCTURE or IBSS_JOINER) //join infrastructure or ad-hoc network with password
+    // ret = join("wlan-ssid", INFRASTRUCTURE or IBSS_JOINER) //join infrastructure or ad-hoc network
+    // ret = join("wlan-ssid", "wlan-passw") //join infrastructure network with password
+    // ret = join("wlan-ssid") //join infrastructure network
+    digitalWrite(9, 1);
+    digitalWrite(8, 1);
+    ret = RedFly.join("wlan-ssid", "wlan-passw", INFRASTRUCTURE);
+    if(ret)
+    {
+      debugoutln("JOIN ERR");
+      for(;;); //do nothing forevermore
+    }
+    else
+    {
+      digitalWrite(7, 1);
+      digitalWrite(6, 1);
+      //set ip config
+      // ret = RedFly.begin(); //DHCP
+      // ret = RedFly.begin(1 or 2); //1=DHCP or 2=Auto-IP
+      // ret = RedFly.begin(ip);
+      // ret = RedFly.begin(ip, dnsserver);
+      // ret = RedFly.begin(ip, dnsserver, gateway);
+      // ret = RedFly.begin(ip, dnsserver, gateway, netmask);
+      ret = RedFly.begin(ip, 0, 0, netmask);
+      if(ret)
+      {
+        debugoutln("BEGIN ERR");
+        RedFly.disconnect();
+        for(;;); //do nothing forevermore
+      }
+      else
+      {
+        digitalWrite(5, 1);
+        RedFly.getlocalip(ip); //receive shield IP in case of DHCP/Auto-IP
+        http = RedFly.socketConnect(PROTO_TCP, server, 80); //start connection to server on port 80
+          if(http == 0xFF)
+          {
+            debugoutln("SOCKET ERR");
+            RedFly.disconnect();
+            for(;;); //do nothing forevermore
+          }
+          else
+          {
+            //send HTTP request
+            RedFly.socketSendPGM(http, PSTR("GET /scroll.php HTTP/1.1\r\nHost: 192.168.0.2\r\n\r\n"));
+          }
+        digitalWrite(4, 1);
+      }
+    }
+  }
+}
+
+void loop()
+{
+ uint8_t sock, buf[32];
+  uint16_t rd, len;
+
+  if(http == INVALID_SOCKET) //no socket open
+  {
+    return;
+  }
+
+  sock = 0xFF; //0xFF = return data from all open sockets
+  rd = RedFly.socketRead(&sock, &len, buf, sizeof(buf));
+  if(sock == http)
+  {
+    if((rd != 0) && (rd != 0xFFFF))
+    {
+      /*if((http_len+rd-250) > sizeof(http_buf)) //overflow
+      {
+        rd = sizeof(http_buf)-http_len;
+      }*/
+      if(http_len >= 250) //ignore header
+      {
+        memcpy(&http_buf[http_len-250], buf, rd);
+      }
+      http_len += rd;
+    }
+    if((rd == 0xFFFF) || (len == 0)) //connection closed or all data received
+    {
+      //close connection
+      RedFly.socketClose(sock);
+
+      //show http buffer
+      //http_buf[sizeof(http_buf)-1] = 0;
+      debugout(http_buf);
+      int start, width=sizeof(http_buf)-1, n=4;
+      for(int x=sizeof(http_buf)-1;x>0;x--)
+      {
+         if(http_buf[x] == 10)
+         {
+           width=start-x;
+           start=x;
+           
+           if (n>0)
+            n--;
+           else
+            break;
+         }
+      }   
+      if(0 && http_buf[start+1] < 32) {//http_buf[start[0]]!='0' && http_buf[start[0]]!='1'
+        digitalWrite(4, !digitalRead(4));
+        http = RedFly.socketConnect(PROTO_TCP, server, 80); //start connection to server on port 80
+        RedFly.socketSendPGM(http, PSTR("GET /led/scroll.php HTTP/1.1\r\nHost: 192.168.0.2\r\n\r\n"));
+      } else {
+        unsigned long ms=0;
+        unsigned long refresh=0;
+        int s=-9;
+        refresh=millis()+5*60*1000;
+        for(;;) {
+          if(millis()>ms) {
+            ms=millis()+100;
+            s++;
+            if (s>=width*7-7) {
+              s=-9;
+              if ( millis() > refresh) {
+                digitalWrite(15, 1);
+                digitalWrite(4, !digitalRead(4));
+                http_len=0;
+                http = RedFly.socketConnect(PROTO_TCP, server, 80); //start connection to server on port 80
+                RedFly.socketSendPGM(http, PSTR("GET /led/scroll.php HTTP/1.1\r\nHost: 192.168.0.2\r\n\r\n"));
+                break;
+              }
+            }
+          }
+          for(int a=15; a<20; a++){
+            digitalWrite(a, 1);
+            for(int b=0; b<10; b++){
+              if(s+b>=0 && s+b<width*7-7)
+                digitalWrite(13-b, ((http_buf[start+1+(s+b)/7+(19-a)*width] - 32) >> ((s+b)%7)) & 1);
+              else
+                digitalWrite(13-b, 0);
+            }
+            delay(1);
+            for(int b=4; b<14; b++){
+              digitalWrite(b, 0);
+            }
+            digitalWrite(a, 0);
+          }
+        }
+      }
+    }
+  }
+}

+ 6 - 0
data.txt

@@ -0,0 +1,6 @@
+
+@$ h"’(#@,  " �(`4�n8@& `  " B"0'|3&`8  ( `# h"—(#‚  ( @ €! ’`<�@‚$! $`cC  €  '„1&  ‚ @, 
+€F"l"st F2�€B!0A€4`J%0I%x()R V(8$pJ!xDda)%`D"l"tt 1u +i@#@x s€t2@0e#lP bRV;0(!!FI!V$29‘2 
+@u h[’h An2@j!0)`|“j$PG%d4i3 J"0‡}2!d<J`H&`t h[wh “t`hjX!€$ rn<1@‚=!Bu`cBJ5€4 —D1!Jj“dB. 
+@t"("b` Ab3`f 0I`00*$0A%d4MB B*0$d"!d$N 9"`t"("q` 1t`hŠD"@d r`00@"5!‚u`pBJ5 =!$D!!JJ2dC" 
+@D <"— #†l2€J �(€1�.80f"x)kS B"X'|#&x9J`I!`C <"— #�H ;yX#@$ —€=€€’4"Bu`{“J5€4 'Ž!&Jdƒdb, 

BIN
img.png


+ 2 - 0
index.php

@@ -0,0 +1,2 @@
+<img src="img.png">
+<div><p><plaintext><?php include('data.txt'); ?>

+ 73 - 0
scroll.php

@@ -0,0 +1,73 @@
+<?php
+ini_set("display_errors", 1);
+error_reporting(E_ALL);
+if(isset($_GET['update'])) echo "Update!";
+
+$name = array("Mon" => "Mo", "Tue" => "Di", "Wed" => "Mi", "Thu" => "Do", "Fri" => "Fr", "Sat" => "Sa", "Sun" => "So");
+$cache_file = "data.txt";
+$url = 'http://api.openweathermap.org/data/2.5/forecast/daily?id=<YourTownId>&appid=<YourAppId>&units=metric';
+
+if (!isset($_GET['update']) && file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 30 ))) {
+   // Cache file is less than five minutes old. 
+   // Don't bother refreshing, just use the file as-is.
+   $txt = file_get_contents($cache_file);
+} else {
+   // Our cache is out-of-date, so load the data from our remote server,
+   // and also save it over our cache for next time.
+	$data = json_decode(file_get_contents($url));
+	$str = "Keine Daten gefunden!";
+	if(!empty($data->city->name)) {
+		$str="";
+		foreach($data->list as $day) {
+			$dt = $name[date("D", $day->dt)];
+			$temp = number_format($day->temp->day, 1, ',', '');
+			$min = number_format($day->temp->min, 0, ',', '');
+			$max = number_format($day->temp->max, 0, ',', '');
+			$wlk = $day->weather[0]->description;
+			if(isset($day->rain)) $rain = $day->rain; else $rain = 0;
+			if(isset($day->snow)) $snow = $day->snow; else $snow = 0;
+			if($rain + $snow > 0.05) $ns = number_format($rain + $snow, 2, ',', '') . "mm"; else $ns = "";
+			$str.="$dt: $min-$max" . "°C $wlk $ns ";
+		}
+	} else {
+	}
+		//echo "<pre>" . json_encode($data, JSON_PRETTY_PRINT) . "</pre>";
+	//echo $str;
+
+	//$str = substr($str,0,123);//126
+	$img_width = strlen($str)*5;
+	$im = imagecreatetruecolor($img_width, 5);
+	
+	// Initialise colours;
+	$black = imagecolorallocate($im, 0, 0, 0);
+	$white = imagecolorallocate($im, 255, 255, 255);
+	$size = imagettftext($im, 4, 0, 5, 5, $white, "/var/www/led/5by5.ttf", $str);
+	if ($size[2] < 615) $width = $size[2]; else $width = 615;
+	imagetruecolortopalette($im, false, 2);
+	$txt = "";
+	for($y=0; $y<5; $y++) {
+	  $txt .= "\n";
+	  $byte=0;
+	  $index=0;
+	  for($x=0;$x<=$width;$x++) {//chr 32 to 160
+			if(imagecolorat($im, $x, $y) != $black) {
+				$byte += 1 << $index;
+			}
+			$index++;
+			if($index >= 7) {
+				$index=0;
+				$txt .= chr($byte+32);
+				$byte=0;
+			}
+	  }
+		if($index < 7) {
+			$txt .= chr($byte+32);
+		}
+	  
+	}
+	if(isset($_GET['update'])) imagepng($im, "img.png");
+	imagedestroy($im);
+    file_put_contents($cache_file, $txt, LOCK_EX);
+}
+echo "" . $txt;
+?>