2017/12/04

MIT Scratch Game: Ghoul Buster

This game, Ghoul Buster, is made by my son Ryan with the MTI Scratch. Ryan is 7th grade now and this was a project he made at school when he was 6th Grade. If you watched to the end, there is a big enemy boss with really powerful thunder weapons to attack the battleship! He is planning to make level 2 of this game.

I am still trying to convince my son to write a tutorial on how to make this...

我兒子今年國一,這個遊戲 Ghoul Buster是他在小學六年級時做的。Ryan 使用了MIT Scratch 做了這個遊戲。玩起來有 Arcade 雷電的感覺!如果你有看到最後面,他設計的大魔王有很強大的閃電來功擊玩家的太空船! 目前他還在試著做出第二關。

目前我正在說服我兒子來寫一篇如何用 Scratch 來做個教學....

#scratch #scratchgame #mitscratch #minigame #game #kids #coding #programming #kidscoding #kidsprogramming #hourofcode #selfmade #selfmadegame #play #playgame #stonez56 #ryan #yuanryan #yuanryangames





2017/11/12

Getting Started with EPS8266-12E Wi-Fi | ESP8266-12E 筆記本



I wanted to test out ESP8266 for a long time. However, I never got it to work until today. There are many tutorials and articles detailed how to make ESP8266 work, but even I followed many of those tutorials step by step mine ESP8266 just didn't work.  It was very frustrating not able to figure out what went wrong.  Anyway, I got it worked today, so it's better for me to write the steps down, not just for blog visitor like you, but also for myself as a good reference later on.

Previous three failed attempts... 😒


Different Version of ESP8266

There are many ESP8266 variations, the one I used for this tutorial is ESP8266-12E. Please refer to this page[2] to get more information for ESP8266 variations.

ESP8266 Pin Assignment

Most of the people probably will solder ESP8266 with metal covers facing up, so I placed a reversed pin assignment on the right side for easier pin reference.

Material Needed:
  • ESP8266-12E * 1
  • Perfboard * 1 
  • Breadboard * 1 
  • Wires - as many as needed
  • Resistors 1K * 4 
  • CP2102 USB-Serial Converter * 1
Tools Needed:
  • Power supply (3.3V)
  • Soldering iron 
  • Solder Tin
  • Plier-wire cutter
  • Plier

Step One: 

ESP8266 has 2mm pin pitch instead of 2.54mm standard pitch. So we have to place it on a prefboard to make connections easier. 

Place ESP8266 on a prefboard and draw its relative size that's larger to accommodate pins along both sides for easier connections with DuPoint wires. Cut down the piece of prefboard with a plier. 

[Important: I later found out from the ESP8266 datasheet recommended to place Wi-Fi antenna outside of prefboard to get better signal reception & transmission.] 😄

Step Two:

Solder wires on each ESP8266 pin to the prefboard as shown below. I found out that after stripped skin of the wires, soldering job just got a little bit easier.

Note: My previous attempt was to solder wires without strip the wire skin and it was more difficult to solder; harder to bend the wires. Be careful, do not short these wires! :) 

Step Three:

Solder 8 pin headers on each side of ESP8266 as shown below.

Step Four: 

Time to connect all wires together. Check out the schematic diagram below for all the connections needed.

Schematic Diagram




ESP8266 Connection:

  1. VCC -> 3.3V power source
  2. EN-CHPD -> 1K resistor -> 3.3V
  3. Reset -> 1K resistor -> 3.3V
  4. TX -> USB/UART RX
  5. RX -> USB/UART TX
  6. GPIO0 -> do not connect anything for this AT command tutorial
  7. GPIO15 -> 1K resistor -> GND
  8. GND -> GND
CP2012 USB/UART Connection
  1. RX -> ESP8266 TX
  2. TX -> ESP8266 RX
  3. GND -> GND (command ground with ESP8266)
NOTE:
  • Supply 3.3V to EPS8266! 5V will burn ESP8266!
  • GPIO-0 is connected to GND: upload Arduino programming code. 
  • GPIO-0 is not connected: Enter AT Command.


Step Five:

Here, I used a red breadboard for wire connections with resistors and the power supply. As long as you follow the schematic diagram above and wiring tips for the connection, it shouldn't be too difficult. (I only use two transistors to share with common pins to VCC and GND.  Not sure if this is a good practice?)


I have purchased an inexpensive power supply as the 3.3V power source. It displayed the how much the current is using, in this case "068mA",  allowing me to see what power was consumed at the particular point of time, which it's very convenient!  I checked ESP8266 datasheet "68mA ~ 71mA" means it's working probably.


Step Six:

Test AT Command. I think this is a quick method to check whether the ESP8266 is working or not. 
  • Connect CP2012 to a Mac USB port
  • Power on power supply with 3.3V 

Arduino IDE Operations:

  • First, let's load ESP8266 Library into Arduino IDE
  • Copy this string "http://arduino.esp8266.com/stable/package_esp8266com_index.json" into Arduino IDE preference -> Settings -> Additional Board Manager URLs. See below in yellow highlighted strings.



  • Select correct Arduino board type. Select "ESPino (ESP-12 module)" If you don't see this option, please restart Arduino IDE to ensure the library is properly loaded.


  • Select Port from port list. My serial port is /dev/cu.SLAB_USBtoUART


    • Click [Tools] - [Serial Monitor] from Arduino IDE to open the serial monitor.
    • Select baud rate from the baud rate list below. Select [115200 baud].  Your ESP8266 might have default baud rate of 9600 or 38400. If 15200 doesn't work, please try all other baud rate values.

    Start AT Command

    • AT:  You should be able to see the terminal replied "AT   OK" back. Congratulation, your ESP8266 is working!

    • AT+GMR: Display ESP8266 firmware version. My ESP8266 is V1.2.0.0 Date: Dec 2, 2016.  
    • AT+CWJAP="Wi-Fi_SSID","Password": Connect to the particular Wi-Fi Access point with the password designated.  As you can see, the WiFi got connected immediately. 
          

    • AT+CWMODE?[1]: Setup ESP8266 working mode. Let's setup ESP8266 to mode 3 both STA and AP. This allows ESP8266 connecting to your Wi-Fi router/Access point as a client also works as a router/Access point allowing other Wi-Fi client connect to it.
      • AT+CWMODE=1: STA (Become a Wi-Fi client to connect to AP)
      • AT+CWMODE=2: AP (Become an Assess point, so other clients can connect to this AP)
      • AT+CWMODE=3: BOTH = STA + AP (As an access point and a Wi-Fi client)

    • AT+CIFSR: Get IP Address. Since we setup CWMODE=3 (STA+AP mode), the first IP you see is AP IP (ESP8266 IP 192.168.4.1), the second IP is the WAN IP(your Wi-Fi IP 192.168.0.105 where ESP8266 is connected to)


    • AT+CWLAP: Scan Wi-Fi AP in the nearby area and show them all in a list.
      Text in first double quotes are WI-Fi SSID.


      • AT+RST: Reset command to reset ESP8266



      It's great! Your ESP8266 is ready to connect to the Internet.

      Load First Arduino Code:

      ESP8266 can be used as an Arduino board itself without buying another Arduino board to work with ESP8266. Let's flash Arduino code into ESP8266 to test it out. 
      1. Connect GPIO0 -> 1K resistor -> GND (Without GPIOpull low, you can't flash code to ESP8266!
      2. Copy the code below into your Arduino IDE and upload the code and the ESP8266-12E
      *********************************************************************************
      IMPORTANT:  After you upload Arduino codes, the AT command will no longer work. If you still prefer use AT command with ESP8266, you have to reflash AT command firmware to enable it. 

      It took me few days to figure out this!
      ***
      ******************************************************************************

      First Arduino code for ESP8266-12E, Connect to Wifi

      This Arduino code below will connect ESP8266 to your WiFi AP/router and display the IP address it obtain.  For this code to work, please replace Wifi_SSID with your Wifi-SSID and Wifi_Password with your own Wifi-Password. Do not forget to open Arduino IDE serial port to see the connection message!

      #include <ESP8266WiFi.h>
      
      void setup()
      {
        Serial.begin(115200);
        Serial.println();
      
        WiFi.begin("Wifi_SSID", "Wifi_Password");
      
        Serial.print("Connecting");
        while (WiFi.status() != WL_CONNECTED)
        {
          delay(500);
          Serial.print(".");
        }
        Serial.println();
      
        Serial.print("Connected, IP address: ");
        Serial.println(WiFi.localIP());
      }
      
      void loop() {}
      
      

      Second Arduino code for ESP8266-12E, Blink

      #include <ESP8266WiFi.h>
      void setup()
      {
        Serial.begin(115200);
        Serial.println();
        pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
      
        WiFi.begin("Wifi-SSID", "Wifi-Password");
      
        Serial.print("Connecting");
        while (WiFi.status() != WL_CONNECTED)
        {
          delay(500);
          Serial.print(".");
        }
        Serial.println();
      
        Serial.print("Connected, IP address: ");
        Serial.println(WiFi.localIP());
      }
      
      void loop() {
        digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                          // but actually the LED is on; this is because 
                                          // it is acive low on the ESP-01)
        delay(1000);                      // Wait for a second
        digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
        delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)
        }
      

      That's all for this step by stpe notes. Hope you are getting something from here! :)

      REFERENCE

      1. ESP8266 Wi-Fi Library Great info to get more about ESP8266 Wi-Fi Library as well as what's AP, STA, and BOTH modes.
      2. Various ESP8266 boards Great info to understand the different types of ESP8266.
      ==============================================================

        EPS8266-12E Wi-Fi 筆記

      真的很高興,這個部落格在這幾天已經超過30萬的瀏覽次數!謝謝大家拜訪Stonez56的部落格來獲取有對你價值的資訊。😁

      長久以來,我一直想測試ESP8266,但是一直沒有成功。雖然,網上有很多教學和文章詳細介紹如何使用ESP8266,但即使我跟著很多這些教學一步一步地做,大部份都失敗了。 很多時候無法弄清楚哪裡出了問題,真是令人非常沮喪。 今天我手上的ESP8266已經正常的能回覆 AT Command,所以我趕快把這些步驟寫下來,不只可以提各位讀者參考,以後也可以作為自己的一份筆記。

      看看我之前失敗的例子...都堆在角落裡!


      不同版本的 ESP8266

      市面上有很多不同的版本,請參考這裡[2] 來了解其它ESP8266版本的差異。


      ESP8266 腳位說明

      ESP8266腳位說明如下。 由於大多數人可能會把ESP8266的金屬蓋朝上焊接,所以我在右側放置了一個反向的腳位,以便於大家參考。

      所需材料:

      •      ESP8266-12E * 1
      •      洞洞板* 1
      •      麵包板* 1
      •      電線 - 十多條
      •      電阻器1K * 4
      •      CP2102 USB 轉換器 * 1

      所需工具:

      •      電源(3.3V)
      •      烙鐵
      •      焊錫
      •      鋼絲鉗
      •      鑷子

      步驟一:

      ESP8266 腳位是 2mm 的間距,而不是2.54mm的標準間距。 所以我們必須把它銲在洞洞板上以方便連接

      先將ESP8266放置在
      洞洞板上,並畫下其相對尺寸較大的尺寸,沿著兩側留下兩三個洞的距離,等會要銲上接腳,便於用杜邦線測試連接。 先用鉗子剪下畫好大小的洞洞板。

      [重要說明:我從ESP8266官方文件中發現,
      Wi-Fi天線不能放在金屬的上方,以便獲得更好的接收信號和處理能力!所以最後我把天線底下的洞洞板都用斜口鉗剪掉!]😄

      步驟二:

      如下所示,把每個ESP8266的腳位上用電線連接到洞洞板上。我發現電線剝皮後,比較容易焊一些。我看許多網友也都這樣做!

      注意:我以前的嘗試是焊接電線時沒有剝掉電線的外皮,焊接起來也比較困難; 也較不容易彎曲電線。 但是請小心,不要把這些電線短路! ☺

      步驟三:

      在ESP8266的兩側焊接上 8 個針腳,如下所示。

      步驟四:

      參考下面的示意圖,把所有電線接好準備測試。

      Schematic Diagram


      ESP8266連接方法:

      •      VCC - &gt; 3.3V 電源
      •      EN-CHPD - &gt; 1K 電阻 - &gt;3.3V
      •      重置 - &gt; 1K 電阻 - &gt;3.3V
      •      TX - &gt; USB / UART RX
      •      RX - &gt; USB / UART TX
      •      GPIO0 - &gt; 請先不要連接任何腳位,才能做 AT Command 測試
      •      GPIO15 - &gt; 1K 電阻 - &gt;GND
      •      GND - &gt;GND

      CP2012 USB / UART連接方法:

      •      RX - &gt; ESP8266 TX
      •      TX - &gt; ESP8266 RX
      •      GND - &gt; GND(ESP8266共同接地)

      注意:

      •      EPS8266只能使用 3.3V 電源! 使用5V會燒掉ESP8266!
      •      GPIO-0連接到GND:可上傳Arduino程式
      •      GPIO-0未連接:可輸入AT Command


      步驟五:

      如下圖,我用一個紅色小麵包板用來連接電阻和電源連接。 只要你按照上面的示意圖和接線提示連接即可。 (我只使用兩個 1K 電阻與VCC和GND共用腳位,不知道這是否是一個好的方法?)

      我買了一台電源供應器來提供3.3V穩定電源。它也可以顯示目前的電流量,如:“068mA”,讓我知道在特定的時間點,電流量是多少,非常方便! 我查了一下ESP8266的資料“68mA〜71mA”,表示它 Wi-Fi 是開啟中工作中。


      步驟六:

      測試AT命令。這是一個檢查ESP8266是否正常運作的快速方法。
      •      將 CP2012 連接到 Mac USB
      •      開啟3.3V電源

      Arduino IDE使用說明:

      •      先讓我們將ESP8266程式資料載入到Arduino IDE 中
      •      將此字串 “http://arduino.esp8266.com/stable/package_esp8266com_index.json” 複製到Arduino IDE Preference - &gt; Settings - &gt; Additional Board Manager URLs:  下方我用黃色標出的字符:



      • 一定要選擇正確的Arduino類型。 在選單中選擇“ESPino(ESP-12 Module)”如果您沒有看到此選項,請重新啟動一次Arduino IDE以確保ESP8266資料有帶進來。


      • 選擇 Port,我的 serial port 設定是 /dev/cu.SLAB_USBtoUART


        • 按一下 [Tools] -> [Serial Monitor] 打開序列埠的監看視窗。
        • 選擇連接速率 baud rate。 我用的是 [115200 baud].  您的ESP8266的內建速率可能是9600或38400.如果15200沒法使用,請嘗試所有其他的速率值。

        開使使用 AT Command:

        • 在最上方的命令列上打 AT,您應該能夠看到監看視窗回答“AT OK”。 恭喜,您的ESP8266已在正常工作中!

        • AT+GMR: 顯示 ESP8266 軔體版本. 我的 ESP8266 是 V1.2.0.0 Date: Dec 2, 2016.  
        • AT+CWJAP="Wi-Fi_SSID","Password": 使用指定的SSID 和 密碼 連接到特定的Wi-Fi分享器或路由器。 監看視窗會顯示,WiFi已連接成功!
              

        • AT+CWMODE?[1]: 設定ESP8266工作模式。讓我們將ESP8266設置為模式3 STA和AP。 這可以讓ESP8266作為客戶端連接到您的Wi-Fi路由器,ESP8266自己也可以作為路由器/,允許其他Wi-Fi客戶端連接到它。
          • AT+CWMODE=1: STA (Become a Wi-Fi client to connect to AP)
          • AT+CWMODE=2: AP (Become an Assess point, so other clients can connect to this AP)
          • AT+CWMODE=3: BOTH = STA + AP (As an access point and a Wi-Fi client)

        • AT+CIFSR: 顯示IP位址。 由於我們設置了CWMODE = 3(STA + AP模式),所以您看到的第一個IP是ESP8266自己的 IP(ESP8266 IP 192.168.4.1),第二個IP是連到Internet的路由器 IP(ESP8266 Wi-Fi IP 192.168.0.105)


        • AT+CWLAP: 掃描附近區域的Wi-Fi 路由器,並將其全部顯示在列表中。
          下方左側第一個雙引號中的文字是各路由器的 SSID。為了安全,我把 mac adress 畫掉了~


          • AT+RST: 重置 ESP8266,讓它重新開機!


          太好了! 您的ESP8266已準備好連接到Internet。

          載入第一個Arduino 程式到 ESP8266:

          其實ESP8266可以當作一般Arduino板來使用,它上面也有很多 I/O 腳位,不要再連另一塊 Arduino 來節省成本。 現在我們把Arduino的程式碼載入到ESP8266中進行測試。
          • 記得連接GPIO0 -&gt; 1K電阻器 - &gt; GND(GPIO0 要 pull low,不然,程式碼無法載入到ESP8266!
          • 將以下程式碼複製到您的Arduino IDE並載入到ESP8266-12E裡
          *********************************************************************************
          重要提示:在您上傳Arduino程碼後,AT命令將不能再使用。 如果您仍然想要使用ESP8266的AT命令,則必須上載AT command 的軔體才能再使用。
          ***
          ******************************************************************************

          第一個 ESP8266-12E 程式,連接到 WiFi AP :

          下面這個Arduino程式碼將啟動ESP8266連接到您的WiFi AP /路由器,並顯示它取得的IP地址。 要使用此程式碼,記得把您的Wifi密碼將Wifi_SSID替換為您的Wifi-SSID和Wifi_Password。

          #include <ESP8266WiFi.h>
          
          void setup()
          {
            Serial.begin(115200);
            Serial.println();
          
            WiFi.begin("Wifi_SSID", "Wifi_Password");
          
            Serial.print("Connecting");
            while (WiFi.status() != WL_CONNECTED)
            {
              delay(500);
              Serial.print(".");
            }
            Serial.println();
          
            Serial.print("Connected, IP address: ");
            Serial.println(WiFi.localIP());
          }
          
          void loop() 
          {}
          

          第二個 ESP8266-12E 程式,  閃爍 ESP8266 內建 LED

          #include <esp8266wifi.h>
          
          void setup()
          {
            Serial.begin(115200);
            Serial.println();
            pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
          
            WiFi.begin("Wifi-SSID", "Wifi-Password");
          
            Serial.print("Connecting");
            while (WiFi.status() != WL_CONNECTED)
            {
              delay(500);
              Serial.print(".");
            }
            Serial.println();
          
            Serial.print("Connected, IP address: ");
            Serial.println(WiFi.localIP());
          }
          
          void loop() {
            digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                              // but actually the LED is on; this is because 
                                              // it is acive low on the ESP-01)
            delay(1000);                      // Wait for a second
            digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
            delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)
            }
          

          OK,希望你從這裡能得到你要的一些資訊!:)

          參考文件:

          1. ESP8266 Wi-Fi Library Great info to get more about ESP8266 Wi-Fi Library as well as what's AP, STA, and BOTH modes.
          2. Various ESP8266 boards Great info to understand the different types of ESP8266.

          2017/09/19

          Weekend Project – Arduino Temperature Meter V2

          In the last tutorial, I have shown how to make a Temperature Meter which records highest, current, and lowest temperature with Arduino Mini Pro and a DS18B20 temperature probe.

          One of the readers suggested me if I could record the highest and lowest temperatures measured into EEEPROM, then I won't lost the highest/lowest temperature once power is down. It's a good idea, but  I thought, it would be a greater idea if I kept both time stamp and high/low temperatures!
          (Writing data to EEEPROM tutorial would be in V3....unfortunately...)

           So, I searched Arduino.cc website and found abundant information about DS1302/DS1307 RTC clock modules. Many people mentioned in forums that DS1302/DS1307 are not very precise and tend to draft of few seconds per week/month. However, DS1302 is quite affordable, so I bought 2 pieces from an auction sites and to give it a try. Reference DS1302RTC data at Arduino.cc

          Functions added in Temperature V2:
          • Display date/time clock and date of week on top of LCD
          • Realtime display both Celsius and Fahrenheit 
          All steps, material, and wiring here are only related DS1302 RTC module. If you want to learn how to build up the entire project, please check previous tutorial for how to wire up LCD, Arduino, and DS18B20 temperature probe from here:  Arduino-Temperature-Tutorial

          During the experiment of adding RTC module, I have encountered few issues and got few advises and suggestions from Google+ communities: Google+ discussion

          If you need Arduino Libraries, come here:
          Get DallasTemperature Arduino Library here!
          Get OneWire Arduino Library here!

          Few notices to share with you:
          • Arduino has internal Time library (Really, I don't know before I started this!)
          • Use the internal clock to count time elapsed 
          • Only update time from RTC module once a day
          • Remove unnecessary delay() commands to ensure every second is displayed




          Material Needed: 
          • DS1302 RTC module 
          • Few jumper wires 



          DS1302 RTC Module Wiring: 
          • VCC to Arduino VCC
          • GND to Arduino GND
          • CLK to Arduino pin 5
          • DAT to Arduino pin 6
          • RST to Arduino pin 7

          Arduino Temperature Meter Schematic V2


          Video Demonstration


          Code: <
          /*
          Temperature Meter 2015-04-05
          
          Material Needed: 
          - Arudino Mini Pro * 1
          - LCD Module 4 x 20 (J204A) * 1
          - Temperature Probe (DS18B20) * 1 
          - Protoboard * 1 
          - 22k resistor * 1
          - Few jumper wires
          
          Wiring:
          - Arduino-GND to GND 
          - Arduino-VCC to VCC 
          - Temperature probe-GND to GND 
          - Temperature probe-VCC to VCC 
          - Temperature probe-Data to 2.2K resistor to VCC 
          - LCD-GND to GND 
          - LCD-VCC to VCC 
          - LCD-SDA to Arduino A4/SDA 
          - LCD-SLC to Arduino A5/SLC 
          - Protoboard VCC/GND to 5V DC power source 
          - Slide switch to VCC/GND (For LCD on/Off, but not shown below)
          */
          //Compatible with the Arduino IDE 1.0
          //Library version:1.1
          #include <Wire.h>
          #include <LiquidCrystal_I2C.h>
          //Used for DS18S20 Temperature sensor
          #include <OneWire.h>
          #include <DallasTemperature.h>
          //Used for DS1302 RTC Clock module
          #include <DS1302RTC.h>
          #include <Time.h>
          
          //Init DS1302 Clock module
          //Set pins: CLK(4), DAT(5), RST(6)
            int CE = 5;
            int IO = 6;
            int CLK = 7;
            
            String DayOfWeek;
            unsigned long previous_time;
            unsigned long secondsInDay = 86400 * 1000; //1000 millis seconds in a second!
            int sync = 0;
            
            DS1302RTC RTC(CE, IO, CLK);
           
            //init Arduino internal clock
            time_t t = now();
            
          
          /*Define for DS18S20 data pins
          *  This data pins needs to connect 220 Om resister and to 5V to work
          */
          #define ONE_WIRE_BUS 4 
          
          //Define for LCD display pins, SLC 3, SDA 2
          #define SCL_CLOCK_PIN 3
          #define SDA_DATA_PIN 2
          
          //Initialize OneWire library for temperature sensor
          OneWire oneWire(ONE_WIRE_BUS);
          DallasTemperature sensors(&oneWire);
          
          // set the LCD address to 0x27 for a 20 chars and 4 line display
          LiquidCrystal_I2C lcd(0x27,20,4); 
          
          
          float HighestTemp = 0.0;
          float CurrentTemp = 0.0;
          float LowestTemp = 0.0;
          
          void setup()
          {
            //Serial.begin(9600); 
            // start temperature sensor
            sensors.begin();
            sensors.requestTemperatures(); //get temperature
            // initialize the LCD
            //You may setup your own clock pin(SCL), data pin(SDA) 2013-12-14
            //Wire.beginOnPins(SCL_CLOCK_PIN, SDA_DATA_PIN);
            lcd.init();
            lcd.backlight();
            
            //Set lowest, highest temperatues 
            CurrentTemp  = sensors.getTempCByIndex(0);
            HighestTemp = CurrentTemp;
            LowestTemp = CurrentTemp;
            
            
            //Show Temperature Meter wording...
            lcd.setCursor(0,1);  
            lcd.print(F("Temperature Meter V2"));
            lcd.setCursor(0,2);  
            lcd.print(F("  by Stonez Chen"));  
            delay(2000);
            //clear LCD
            lcd.clear();
            
            lcd.setCursor(0,1);
            lcd.print(F("High:"));
            LCDshowNum(5,1,HighestTemp);    
               
            lcd.setCursor(0,2);
            lcd.print(F("Now:"));
            LCDshowNum(4,2,CurrentTemp);  
              
            lcd.setCursor(0,3);
            lcd.print(F("Low:"));
            LCDshowNum(4,3,LowestTemp); 
            
            
            
            
            //Check DS1302 Clcock module time
            if(RTC.haltRTC()){
                lcd.setCursor(0,0);  
                lcd.print(F("1302 Stop,do SetTime"));
            }
          
            //Read time from DS1302 moudle and setup internal clock
            setSyncProvider(RTC.get);
            while(timeStatus() != timeSet){ 
                  setSyncProvider(RTC.get);
            }
            
            t = now();
            
            if(timeStatus() == timeSet){
                  previous_time = millis();
                  /*
                  Serial.println("Init Year = " + String(year(t)));        
                  Serial.println("Init Month = " + String(month(t)));
                  Serial.println("Init Day = " + String(day(t)));        
                  Serial.println("Init Hour = " + String(hour(t)));
                  Serial.println("Init minute = " + String(minute(t)));
                  Serial.println("Init second = " + String(second(t)));
                  */
          
            }else{
                  //Serial.println("Time not set!");
            }
           
          }
          
          void loop()
          { 
              unsigned long current_time = millis();
              unsigned long time_passed;
          
              //Sync clock every 24hr(secondsInDay)
              time_passed = current_time - previous_time;
              if(time_passed >= secondsInDay){
                 setSyncProvider(RTC.get);
                 sync++;
                 previous_time = current_time;
              }
              
             //mark when RTC.get again!
            //Serial.print(" Time_passed = " + String(time_passed));
            //Serial.println(" Synced :" + String(sync));
            //lcd.setCursor(18,3);  
            //lcd.print(sync);
            
            //Print Date time on the first line
            lcd.setCursor(0,0);  
            lcd.print(printYMDHMS());
          
            
            sensors.requestTemperatures(); //get temperature
          
            //Get Current
            CurrentTemp = sensors.getTempCByIndex(0);
            LCDshowNum(4,2,CurrentTemp);   
            
            //Check if Hightest
            if(CurrentTemp > HighestTemp){
               HighestTemp = CurrentTemp;
               LCDshowNum(5,1,HighestTemp);     
            }
          
            //Chekc if Lowest
            if(CurrentTemp < LowestTemp){
              LowestTemp = CurrentTemp;
              LCDshowNum(4,3,LowestTemp);
            }
            delay(200);
            
          }
          
          /*
          * LCDshowNum
          * LCD display location: x, y
          * Float n: temperature to display
          */
          void LCDshowNum(int x, int y, float n){
            lcd.setCursor(x,y);
            lcd.print(n,1); //,1 means print 1 decimal
            lcd.print(char(223)); 
            lcd.print("C ");
            lcd.print(((n*1.8)+32),1);//,1 means print 1 decimal
            lcd.print(char(223)); 
            lcd.print("F ");
          }
          
          /*
          * This function return YYMMDD HHMMSS string from internal clock
          */
          String printYMDHMS(){
            
            String DayOfWeek = "";
            t = now(); //update internal clock
           
            switch (weekday(t)){
                case 7:
                  DayOfWeek = " SA";
                  break;
                case 6:
                  DayOfWeek = " FR";
                  break;
                case 5:
                  DayOfWeek = " TH";
                  break;
                case 4:
                  DayOfWeek = " WE";
                  break;          
                case 3:
                  DayOfWeek = " TU";
                  break;
                case 2:
                  DayOfWeek = " MO";
                  break; 
                 case 1:
                  DayOfWeek = " SU";
                  break;         
              }
          
              return
                String(year(t)).substring(2,4) + '/' +
                String(print2digits(month(t))) + '/' +
                String(print2digits(day(t))) + ' ' +
                String(print2digits(hour(t))) + ':' +
                String(print2digits(minute(t))) + ':' +
                String(print2digits(second(t))) +
                DayOfWeek;
          }
          /*
          * Add 0 to the single digit number to better align the text
          */
          
          String print2digits(int number) {
            if (number >= 0 && number < 10){
              return '0'+String(number);
            }else{
              return(String(number));
            }
          }
          
          


          Copyright Notice:
          You are welcome to share this tutorial with others, please retain author's name and URL link to this tutorial blog page. Thank you!

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

          自製 Arduino 溫度測量機 V2


          在上一次的教學中, 我已示範過如何用 Arduino + 溫度測量棒 + LCD 來 自製溫度測量機 。
          有讀者看到上一個教學後建議我把最高溫及最低溫的資訊記錄到EEEPROM裡,這樣高低溫資訊才不會遺失。 聽起來很不錯,但如果能把時間+高低溫也一起記錄下來, 應會更好。
          所以我上網找了Arduino 與時間相關的資訊,也很快的找到了 DS1302/DS1307 RTC 時鐘模組可以記錄時間,而且即使系統斷電時,時鐘模組可以依靠著內建的 2302 水銀電池來維持時間運作。

          搜尋資訊的同時,很多人都提到 DS1302/DS1307不是很準確,用一段時間就會慢個幾秒鐘, 但是它相對便宜,所以我就買了兩片DS1302回來試試囉!  請參考 DS1302 RTC 詳細介紹

          溫度測量機 V2 新增功能

          • 顯示日期  時間  星期 
          • 顯示攝氏 及 華氏 
          這次的的教學主要是以如何加入 DS1302 RTC 模組. 如果你要做一個完整的測量機,請先參考上一篇:  自製溫度測量機

          把 DS1302 RTC 模組加入到電路中不難,但是我遇到了一些很奇怪的問題,如只能顯示單數秒之類的。還好 Google+ 社群裡有許多朋友給了我建議及方向,讓我能及時把程式寫好並測試完成 。相關討論 Google+ discussion

          使用 DS1302 RTC 主要的注意事項如下:
          • Arduino 有內建 Time 程式庫 (說真的,開始寫程式時,我還真的不知道哩! Orz...)
          • 使用Arduino內建的時鐘來當計時器即可! 
          • 每天只要向 RTC 模組要一次時間來更新 Arduino內建時鐘即可
          • 檢視一下程式中如果用到 delay() 次數及時間長短,它會顯嚮秒數的顯示




          所需材料: 
          • DS1302 RTC 時鐘模組 
          • 跳線數根 



          DS1302 RTC 模組接線: 
          • VCC to Arduino VCC
          • GND to Arduino GND
          • CLK to Arduino pin 5
          • DAT to Arduino pin 6
          • RST to Arduino pin 7

          Arduino 溫度測量機線路圖 V2


          影片展示


          程式碼: (請參考英文版部份)

          Copyright Notice:
          You are welcome to share this tutorial with others, please retain author's name and URL link to this tutorial blog page. Thank you!

          2017/09/16

          Testing Arduino POV (Persistent of Vision) | 試試 Arduino POV (視覺暫留)

          I have been attracted to Arduino POV[1] for quite a while, but I didn't have a chance to actually make it myself.   Luckily, I found this easy to follow Arduino POV tutorial[2] on Instructable.com and within an hour, my son and me made two Arduino POV sets and have fun for the entire afternoon.


          Material needed for this tutorial:

          • Arduino Nano * 1 (All other kinds of Arduino board will do)
          • LED * 7
          • 220 resistor * 7 
          • Jump wire ~ up to 10 (female to male)
          • Prefboard * 1 
          • Battery pack (If you would like have fun without tethered with USB)

          Easy Wire Connection as follow:

          1. LED1 ~ LED7 negative pin to Prefboard GND
          2. Prefboard to Nano(or Uno) GND pin
          3. LED1 ~ LED7 postive pin to Nano(or Uno) D2 ~ D8 pin
          4. USB power to Nano USB port to supply power (or use a battery back to supply power)

          Schematic: (I use www.tinkercad.com to draw this schematic below, just in case you interested.)



          This is a fun a easy project! First, just connect LED cathode(negative) and resistors on the prefboard.
          Then Preboard GND to Arduino Nano GND.


          Then connect these LED positive pins to Arduino Nano.





          As you can see in the picture below, I'v used Arduino Nano. It's lighter and smaller for portable devices.  I made the Red one and my son have choose the Green.



          Programming logic:
          When anyone sees an image, the image stays in the retina of the eyes for roughly 1/16th seconds. We can utilize the particular physical characteristic of human eyes, to crate the Arduino POV project. The basic idea is when we want to show a letter, Arduino shows each column of a letter at a time to form the letter to eyes.

          See the illustration below on how to show a letter 'H'. First, Arduino displays column 1 to light up all 7 LEDs at timing 1. While column 1 image stays in human eyes, Arduino shows 2nd column, then 3, 4, and 5th columns at their respectively timing 2~5. Since all these images stays in human eyes temporarily, we will see the letter 'H'.



          Actual LED image captured:



          Arduino code here:
          Just copy and past into Arduino IDE and it should work.
          *Change your own message in the variable msgBody and remember to change msgLength*

          /*
           Written by Ahmad Saeed on 22 August 2015
           
           This code is capable of displaying the following characters;
           0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ .-_!%&#$,()@?
          */ 
          
          //////////////////// Message to Customize  ///////////////////
          #define msgLength 11                                       ///
          String msgBody = "This is POV";                            ///
          //////////////////////////////////////////////////////////////
          //////////////////////////////////////////////////////////////
          
          
          
          
          #define delayInChar 3
          #define delayBetweenChar 5
          #define LED1 2
          #define LED2 3
          #define LED3 4
          #define LED4 5
          #define LED5 6
          #define LED6 7
          #define LED7 8
          
          byte msgCode[(5 * msgLength) + 10];
          boolean pintState;
          int columnNum = -1;
          String charToWrite;
          
          void setup() {
            msgBody.toUpperCase();
            pinMode(LED1, OUTPUT);
            pinMode(LED2, OUTPUT);
            pinMode(LED3, OUTPUT);
            pinMode(LED4, OUTPUT);
            pinMode(LED5, OUTPUT);
            pinMode(LED6, OUTPUT);
            pinMode(LED7, OUTPUT);
          }
          
          void loop() {
          //// Convert all text to binary array ////////////////////////
            if ( columnNum == -1 ) // This block needs to be done once//
            {                                                         //
              for (int c = 0; c < (msgBody.length()); c++)  {         //
                //Separate the following character                    //
                charToWrite = msgBody.substring(c, c + 1);            //
                //Send the separated characted to addChar function    //
                addChar(charToWrite);                                 //
              }                                                       //
                //Add a little space after each character             //
              addChar(" ");                                           //
              addChar(" ");                                           //
            }                                                         //  
          //////////////////////////////////////////////////////////////
          
          //// Display the binary arrays after all characters are coded //
            for (int c = 0; c < (sizeof(msgCode)); c++)  {              //
              pintState = (msgCode[c] / B1000000) % B10;                //
              digitalWrite(LED1, pintState);                            //
                                                                        //
              pintState = (msgCode[c] / B100000) % B10;                 //
              digitalWrite(LED2, pintState);                            //
                                                                        //
              pintState = (msgCode[c] / B10000) % B10;                  //
              digitalWrite(LED3, pintState);                            //
                                                                        //
              pintState = (msgCode[c] / B1000) % B10;                   //
              digitalWrite(LED4, pintState);                            //
                                                                        //
              pintState = (msgCode[c] / B100) % B10;                    //
              digitalWrite(LED5, pintState);                            //
                                                                        //
              pintState = (msgCode[c] / B10) % B10;                     //
              digitalWrite(LED6, pintState);                            // 
                                                                        //
              pintState = msgCode[c] % B10;;                            //
              digitalWrite(LED7, pintState);                            //
                                                                        //
              delay(delayInChar);                                       //
              // if the character is finished, take a longer off period //
              if ((c + 1) % 5 == 0 ) {                                  //
                digitalWrite(LED1, LOW);                                //
                digitalWrite(LED2, LOW);                                //
                digitalWrite(LED3, LOW);                                //
                digitalWrite(LED4, LOW);                                //
                digitalWrite(LED5, LOW);                                // 
                digitalWrite(LED6, LOW);                                //
                digitalWrite(LED7, LOW);                                //
                delay(delayBetweenChar);                                //
              }                                                         //
            }                                                           //
                                                                        //
          ////////////////////////////////////////////////////////////////
          }     
          
          
          void addChar(String y) {
            if (y == "1") {
              addColumn(B0010001);
              addColumn(B0100001);
              addColumn(B1111111);
              addColumn(B0000001);
              addColumn(B0000001);
            }
            else if (y == "2") {
              addColumn(B0100001);
              addColumn(B1000011);
              addColumn(B1000101);
              addColumn(B1001001);
              addColumn(B0110001);
            }
            else if (y == "3") {
              addColumn(B0100010);
              addColumn(B1000001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B0110110);
            }
            else if (y == "4") {
              addColumn(B0001100);
              addColumn(B0010100);
              addColumn(B0100100);
              addColumn(B1111111);
              addColumn(B0000100);
            }
            else if (y == "5") {
              addColumn(B1110010);
              addColumn(B1010001);
              addColumn(B1010001);
              addColumn(B1010001);
              addColumn(B1001110);
            }
            else if (y == "6") {
              addColumn(B0111110);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B0100110);
            }
            else if (y == "7") {
              addColumn(B1000000);
              addColumn(B1000111);
              addColumn(B1001000);
              addColumn(B1010000);
              addColumn(B1100000);
            }
            else if (y == "8") {
              addColumn(B0110110);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B0110110);
            }
            else if (y == "9") {
              addColumn(B0110010);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B0111110);
            }
            else if (y == "0") {
              addColumn(B0111110);
              addColumn(B1000101);
              addColumn(B1001001);
              addColumn(B1010001);
              addColumn(B0111110);
            }
            else if (y == "A") {
              addColumn(B0011111);
              addColumn(B0100100);
              addColumn(B1000100);
              addColumn(B1000100);
              addColumn(B1111111);
            }
            else if (y == "B") {
              addColumn(B1111111);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B0110110);
            }
            else if (y == "C") {
              addColumn(B0111110);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B0100010);
            }
            else if (y == "D") {
              addColumn(B1111111);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B0111110);
            }
            else if (y == "E") {
              addColumn(B1111111);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1000001);
            }
            else if (y == "F") {
              addColumn(B1111111);
              addColumn(B1001000);
              addColumn(B1001000);
              addColumn(B1001000);
              addColumn(B1000000);
            }
            else if (y == "G") {
              addColumn(B0111110);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B1000101);
              addColumn(B0100110);
            }
            else if (y == "H") {
              addColumn(B1111111);
              addColumn(B0001000);
              addColumn(B0001000);
              addColumn(B0001000);
              addColumn(B1111111);
            }
            else if (y == "I") {
              addColumn(B0000000);
              addColumn(B1000001);
              addColumn(B1111111);
              addColumn(B1000001);
              addColumn(B0000000);
            }
            else if (y == "J") {
              addColumn(B0000000);
              addColumn(B0000010);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B1111110);
            }
            else if (y == "K") {
              addColumn(B1111111);
              addColumn(B0001000);
              addColumn(B0010100);
              addColumn(B0100010);
              addColumn(B1000001);
            }
            else if (y == "L") {
              addColumn(B1111111);
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B0000001);
            }
            else if (y == "M") {
              addColumn(B1111111);
              addColumn(B0100000);
              addColumn(B0011000);
              addColumn(B0100000);
              addColumn(B1111111);
            }
            else if (y == "N") {
              addColumn(B1111111);
              addColumn(B0010000);
              addColumn(B0001000);
              addColumn(B0000100);
              addColumn(B1111111);
            }
            else if (y == "O") {
              addColumn(B0111110);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B1000001);
              addColumn(B0111110);
            }
            else if (y == "P") {
              addColumn(B1111111);
              addColumn(B1001000);
              addColumn(B1001000);
              addColumn(B1001000);
              addColumn(B0110000);
            }
            else if (y == "Q") {
              addColumn(B0111100);
              addColumn(B1000010);
              addColumn(B1000010);
              addColumn(B1000010);
              addColumn(B0111101);
            }
            else if (y == "R") {
              addColumn(B1111111);
              addColumn(B1001000);
              addColumn(B1001100);
              addColumn(B1001010);
              addColumn(B0110001);
            }
            else if (y == "S") {
              addColumn(B0110010);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B1001001);
              addColumn(B0100110);
            }
            else if (y == "T") {
              addColumn(B1000000);
              addColumn(B1000000);
              addColumn(B1111111);
              addColumn(B1000000);
              addColumn(B1000000);
            }
            else if (y == "U") {
              addColumn(B1111110);
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B1111110);
            }
            else if (y == "V") {
              addColumn(B1111100);
              addColumn(B0000010);
              addColumn(B0000001);
              addColumn(B0000010);
              addColumn(B1111100);
            }
            else if (y == "W") {
              addColumn(B1111110);
              addColumn(B0000001);
              addColumn(B0000110);
              addColumn(B0000001);
              addColumn(B1111110);
            }
            else if (y == "X") {
              addColumn(B1100011);
              addColumn(B0010100);
              addColumn(B0001000);
              addColumn(B0010100);
              addColumn(B1100011);
            }
            else if (y == "Y") {
              addColumn(B1110000);
              addColumn(B0001000);
              addColumn(B0001111);
              addColumn(B0001000);
              addColumn(B1110000);
            }
            else if (y == "Z") {
              addColumn(B1000011);
              addColumn(B1000101);
              addColumn(B1001001);
              addColumn(B1010001);
              addColumn(B1000011);
            }
            else if (y == "Z") {
              addColumn(B1000011);
              addColumn(B1000101);
              addColumn(B1001001);
              addColumn(B1010001);
              addColumn(B1000011);
            }
            else if (y == " ") {
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B0000000);
            }
            else if (y == ".") {
              addColumn(B0000000);
              addColumn(B0000011);
              addColumn(B0000011);
              addColumn(B0000000);
              addColumn(B0000000);
            }
            else if (y == "_") {
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B0000001);
              addColumn(B0000001);
            }
            else if (y == "-") {
              addColumn(B0000000);
              addColumn(B0001000);
              addColumn(B0001000);
              addColumn(B0001000);
              addColumn(B0000000);
            }
            else if (y == "!") {
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B1111101);
              addColumn(B0000000);
              addColumn(B0000000);
            }
            else if (y == "(") {
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B0111110);
              addColumn(B1000001);
            }
            else if (y == ")") {
              addColumn(B1000001);
              addColumn(B0111110);
              addColumn(B0000000);
              addColumn(B0000000);
              addColumn(B0000000);
            }
            else if (y == "%") {
              addColumn(B1100010);
              addColumn(B1100100);
              addColumn(B0001000);
              addColumn(B0010011);
              addColumn(B0100011);
            }
            else if (y == ",") {
              addColumn(B0000000);
              addColumn(B0000101);
              addColumn(B0000110);
              addColumn(B0000000);
              addColumn(B0000000);
            }
            else if (y == "?") {
              addColumn(B0100000);
              addColumn(B1000101);
              addColumn(B1001000);
              addColumn(B0110000);
              addColumn(B0000000);
            }
            else if (y == "#") {
              addColumn(B0010100);
              addColumn(B0111110);
              addColumn(B0010100);
              addColumn(B0111110);
              addColumn(B0010100);
            }
            else if (y == "@") {
              addColumn(B0111110);
              addColumn(B1000001);
              addColumn(B1011101);
              addColumn(B1011101);
              addColumn(B0111000);
            }
            else if (y == "$") {
              addColumn(B0110010);
              addColumn(B1001001);
              addColumn(B1111111);
              addColumn(B1001001);
              addColumn(B0100110);
            }
          }
          
          void addColumn(byte x) {
            columnNum += 1;
            msgCode[columnNum] = (x);
          }
          
          
          
          
          Image captured with my POV set:




          Image captured with my son's POV set:


          How to capture the image:
          I used HTC U11 to shot these photos. First, you have change HTC camera to Pro mode and set the exposure time to greater than 2 seconds to capture this image. Hold the Arduino POV set steadily on one hand and move the POV set slowly towards to left from right.  I believe any camera with Bulb exposure time greater than 2 seconds should be able to capture this image. 

          That's all for this tutorial. See you next time!

          Article feferences:
          1. Wikipedia for POV
          2. How to Make a POV Display Using LEDs and Arduino 
          3. Simple-Arduino-POV-Wand 


          Done.

          ==== 中 文 版 本 ====

          自從我看個幾個 Arduino POV[1] 專案之後,一直想自己試試做一個來玩玩,但一直有點懶惰,遲遲沒有動手。最近看到一篇很簡單的教學 Arduino POV tutorial[2] ,剛好兒子也在家,我們決定一起動手來做一個來玩。只需約一小時,我們就各自做了一組 Arduino POV,而且整個下午都在試著不同的字串及拿著 HTC U11 拍出很一些有趣的照片。這是一個很好的親子活動的安排哩!現在就看著這篇教學一起動手吧!


          這篇教學所需材料:

          • Arduino Nano * 1 (Nano, Pro mini, Uno 都可以)
          • LED * 7
          • 220 歐姆電阻 * 7 
          • 杜邦線 ~ 約 10條 (母對母)
          • 洞洞板 * 1 
          • 電池盒 (不用連接USB,可以更方便的玩,但可有可無)

          接線方式:
          1. LED1 ~ LED7 負級 to 220 歐姆電阻
          2. 電阻 to Nano(or Uno) GND
          3. LED1 ~ LED7 正級 to Nano(or Uno) D2 ~ D8 腳位
          4. USB 電源接 Nano USB 來提供電源 (這可以用電池盒來取代)

          電路圖: (我是用 www.tinkercad.com 來製作這張電路圖)



          這真的是一個很簡單又好玩的範例! 
          道先, 先把 LED 負級連到220歐姆的電阻再由電阻連接到洞洞板的負極上。


          接著,把LED 1 ~ 7 的正極接到 Arduino 上的 D2 ~ D8 腳位上。





          我這次是使用了 Arduino Nano,因為它的體積比較小。下圖中可以看到我們做了兩組,我做了紅色的這組,我兒子則做了綠色的這一組。



          程式的邏輯如下:
          原理是當我們看到一個影像時,這個影像會暫留在視網膜上約 1/16 秒。當影像一個接著一個的顯示後,我們即會看到好像是數個影像的重疊,這些重疊的影像看起來就會形成一幅影像;卡通或動畫即是這樣的原理。Arduino POV 就是利用同樣的原理。

          看下例如何顯示 H 字母。首先,Arduino 在 Time 1 顯示了欄位 1 的 7 個 LED,然後 Arduino 在 Time 2 ~ 5 個別的顯示欄位 2 ~ 5。 由於每個欄位都會在視網膜上暫留,我們就可以在到字母 'H'。


          你可以參考這幾個字母放大後的影像如下:



          Arduino 程式碼在上方,直接拷貝就可以使用:

          *如果你要改變顯示的字串,請記得改變 msgBody 字串以及 msgLength 的字串長度*

          
          
          
          
          
          
          下方是我用 HTC U11 照出來的 POV 照片:




          這張是用我兒子那一組所拍下來的POV照片


          如何照下 Arduino POV 的照片:
          我是使用 HTC U11 來拍攝這些照片的。首先,你必需把手機設定到 PRO 模式 ,然後選定曝光時間到 2 秒以上才能拍的出來。拍攝時,拿著洞洞板,把 LED 朝相機方向,慢慢的由左到右的移動。不過,任何可以選定手動曝光到 2 秒以上的相機應該都可以拍的。

          這就是這次的Arduino 範例,下次見!

          文章參考:
          1. Wikipedia for POV
          2. How to Make a POV Display Using LEDs and Arduino 
          3. Simple-Arduino-POV-Wand