Wio Lite RISC V GD32VF103 with ESP8266

Wio Lite RISC-Vは、GD32VF103をベースとしたフェザーフォームファクターのRISC-V開発ボードで、オンボードのESP8266 Wio CoreによりWiFi機能も備えています。
GD32VF103CBT6は、Nuclei System Technologyに基づくBumblebeeコアです。RV32IMAC命令セットとECLIC高速割り込み機能をサポートしています。コアの消費電力は従来のCortex-M3のわずか1/3です。
オンボードのESP8266 WiFiコアとLipo充電回路により、IoT制御ボードとして最適です。また、このボードの裏面にはマイクロSDスロットがあり、システムリソースを拡張することができます。
さらに、Wio Liteボードとして、Wio Lite RISC-Vは間違いなくGrove Shield for Wio Liteと連携して動作します。このシールドを使用することで、200以上のGroveセンサー、アクチュエータ、ディスプレイを利用できます。例えば、好きなGrove OLEDを選んで、視覚的な開発ボードを作成することができます。
特徴
- RISC-V MCU GD32VF103CBT6
 - ESP8266 WiFi Wio Core
 - フェザーフォームファクター
 - JST2.0 Lipoポート
 - オンボードSDスロット
 - USB Type C
 
ハードウェア概要

対応プラットフォーム
| PlatformIO | Arduino | Raspberry Pi | ||
|---|---|---|---|---|
![]()  | ![]()  | ![]()  | ![]()  | ![]()  | 
はじめに
PlatformIOで始める
ハードウェア
必要な材料
- ステップ 1 Wio LiteとPCをUSB Type C to Aケーブルで接続し、電源供給とダウンロード用のシリアルポートを確保します。
 
ソフトウェア
RISC-V GD32はすでにArduinoフレームワークを使用したPlatformIO IDEをサポートしていますが、Arduino IDEはまだサポートされていません。
- ステップ 1
 
PlatformIO IDEをセットアップします。PlatformIO IDEはVisual Studio Codeをベースにしています。 Visual Studio Codeをダウンロードしてください。 Visual Studio Codeの左側にある「拡張機能」アイコンをクリックします。

検索エンジンに「platformIO」と入力してインストールします。

- ステップ 2
 
PlatformIO IDEを開き、「新しいプロジェクト」をクリックしてプロジェクトを作成します。プロジェクト名を入力し、ボードとしてGD32VF103V-EVAL(Sipeed)を選択します。フレームワークはArduinoを選択し、「完了」をクリックします。
- ステップ 3
 
Arduinoフレームワークのコードを編集し、Visual Studio Codeの下部にあるコンパイルボタンをクリックします。

- ステップ 4
 
コードはバイナリファイルにコンパイルされます。DFUツールを使用してバイナリファイルをボードにダウンロードできます。また、DFUファームウェアをインストールして、DFU方式でコードをダウンロードできるようにする必要があります。DFUファームウェアはDFUツールの同じドキュメントに含まれています。
- ステップ 5
 
Wio Liteのリセットボタンを押し、左側のブートスイッチをオンにすると、DFUツールがボードを認識します。DFUツールフレームウェアをインストールした後、ブートスイッチを右側に切り替え、コンパイルされたバイナリファイルをボードのフラッシュにダウンロードします。「Leave DFU」をクリックしてボードをDFUツールから切断すると、コードが正しくボードに書き込まれます。

ウェブサイトを使用してオンボードユーザーLEDを制御するデモ
ハードウェア
必要な材料
- Wio Lite RISC-V (GD32VF103) - With ESP8266
 - UartSBee V5のような任意のUSB to TTLアダプター
 - USB 3.1 Type C to A ケーブル
 
- ステップ 1 USB to TTLアダプターを使用してWio Liteのシリアルポートに接続します。(Wio LiteのシリアルポートはピンPA9-TX、PA10-RXです)
 - ステップ 2 別のUSB to TTLアダプターを使用してESP8266のシリアルポートに接続します。(ESP8266のデータ送信を監視したい場合)
 - ステップ 3 Wio LiteとPCをUSB Type C to Aケーブルで接続し、電源供給とダウンロード用のシリアルポートを確保します。
 
ソフトウェアコード
#include <Arduino.h>
const bool printReply = true;
const char line[] = "-----\n\r";
int loopCount=0;
 
char html[50];
char command[20];
char reply[500]; // 通常はこのようにしません
 
char ipAddress [20];
char LED[30];
int lenHtml = 0;
char temp[5];
 
void getReply(int wait)
{ 
    int tempPos = 0;
    long int time = millis();
    while( (time + wait) > millis())
    {   
        while(Serial1.available()>0)
        {   
            char c = Serial1.read(); 
            if (tempPos < 500) { reply[tempPos] = c; tempPos++;   }
        }
        reply[tempPos] = 0;
    } 
   
    if (printReply) { Serial.println( reply );  Serial.println(line);     }
}
void setup() 
{
  Serial.begin(115200);  // GD32のシリアルポート
  Serial1.begin(115200);  // ESP8266のシリアルポート
  pinMode(LED_BUILTIN, OUTPUT);
  
  delay(3000);
  Serial1.println("AT+CWQAP");
  getReply(2000);
  Serial1.println("AT+CWMODE=1");
  getReply(2000);
  Serial1.println("AT+CWJAP=\"Your WiFi SSID\",\"Password\""); // 自分のWiFiを追加
  getReply(5000);
  Serial1.print("AT+CIFSR\r\n");
  getReply(2000);
  
   int len = strlen( reply ); 
      bool done=false;
      bool error = false;
      int pos = 0;
      while (!done)
      {
           if ( reply[pos] == 34) { done = true;} 
           pos++;
           if (pos > len) { done = true;  error = true;}
      }
 
      if (!error)
      {
            int buffpos = 0;
            done = false;
            while (!done)
            {
               if ( reply[pos] == 34 ) { done = true; }
               else { ipAddress[buffpos] = reply[pos];    buffpos++; pos++;   }
            }
            ipAddress[buffpos] = 0;
      }
      else { strcpy(ipAddress,"ERROR"); }
      Serial.println(ipAddress);
      Serial1.print("AT+CIPMUX=1\r\n");
      getReply( 1500 );
      Serial1.print("AT+CIPSERVER=1,80\r\n");
      getReply( 1500 );
      
      
}
void loop()
{
          if(Serial1.available()) // ESP8266がデータを送信しているか確認
        {
          // これは+IPDの返信です - 非常に長いです。
          // 通常はメッセージ全体を変数にコピーする必要はありません。「HOST」までコピーするだけで十分です。
          // または、シリアルポートを読み取る際にデータを文字ごとに検索することもできます。
        
          getReply( 2000 );      
 
 
          bool foundIPD = false;
          for (int i=0; i<strlen(reply); i++)
          {
               if (  (reply[i]=='I') && (reply[i+1]=='P') && (reply[i+2]=='D')   ) { foundIPD = true;    }
          }
 
 
          if ( foundIPD  )  
          {
 
              loopCount++;
              // Serial.print( "リクエストがあります。ループ = ");  Serial.println(loopCount); Serial.println(""); 
            bool LEDstate = false;
            int LEDstatepos = 0;
              for (int i=0; i<strlen(reply); i++)
              {
                   if (!LEDstate) // 最初の名前の出現のみ取得
                   {
                         if ( (reply[i]=='L') &&  (reply[i+1]=='E')&&  (reply[i+2]=='D')&&  (reply[i+3]=='=')) 
                         { 
                             LEDstate = true;
                             LEDstatepos = i+4;
                           
                         }
                        
                   }     
              }
                  if (LEDstate)
              {
                    int tempPos = 0;
                    bool finishedCopying = false;
                    for (int i= LEDstatepos; i<strlen(reply); i++)
                    {
                         if ( (reply[i]==' ') && !finishedCopying )  { finishedCopying = true;   } 
                         if ( !finishedCopying )                     { LED[tempPos] = reply[i];   tempPos++; }
                    }              
                    //LED[tempPos] = 0;
              }
 
              if (LEDstate) { Serial.print( "LED状態 = ");  Serial.println(LED); Serial.println("");
                         
              } 
              else          { Serial.println( "形式が不正です");   Serial.println("");           }
              
              Serial.println("111");
              Serial.println(LED);
              Serial.println("000");
                  if(strcmp(LED,"on")==0){digitalWrite(LED_BUILTIN, HIGH); }
                  if(strcmp(LED ,"off")==0){digitalWrite(LED_BUILTIN, LOW); }
            strcpy(html,"<html><head></head><body>");
            strcpy(command,"AT+CIPSEND=0,25\r\n");
            Serial1.print(command);
            getReply(2000);
            Serial1.print(html);
            getReply(2000);
            strcpy(html,"<h1>LEDテスト</h1>");
            strcpy(command,"AT+CIPSEND=0,17\r\n");
            Serial1.print(command); 
            getReply(2000);      
            Serial1.print(html);
            getReply(2000);
            strcpy(html,"<p>LEDステートメント</p>");
            strcpy(command,"AT+CIPSEND=0,19\r\n");
            Serial1.print(command);  
            getReply(2000);     
            Serial1.print(html);
            getReply(2000);
            
                if (LEDstate)
             {
                  // 名前を書き込む
                  strcpy(html,"<p>LED状態は "); strcat(html, LED ); strcat(html,"</p>");
 
                  // cipsendコマンドのためにhtmlの長さが必要
                  lenHtml = strlen( html );
                  strcpy(command,"AT+CIPSEND=0,"); __itoa( lenHtml, temp, 10); strcat(command, temp); strcat(command, "\r\n");
                  Serial1.print(command);
                  getReply( 2000 );          
                  Serial1.print(html);
                  getReply( 2000 );                           
             }
 
 
              strcpy(html,"<form action=\""); strcat(html, ipAddress); strcat(html, "\" method=\"GET\">"); strcat(command, "\r\n");
 
              lenHtml = strlen( html );
              __itoa( lenHtml, temp, 10);
              strcpy(command,"AT+CIPSEND=0,"); 
              __itoa( lenHtml, temp, 10); 
              strcat(command, temp);  
              strcat(command, "\r\n");
 
              Serial1.print(command);
              getReply( 2000 );          
              Serial1.print(html);
              getReply( 2000 );          
 
              strcpy(html,"LED状態:<br><input type=\"text\" name=\"LED\">");
              strcpy(command,"AT+CIPSEND=0,43\r\n");
              Serial1.print(command);
              getReply( 2000 );
              Serial1.print(html);         
              getReply( 2000 );         
 
              strcpy(html,"<input type=\"submit\" value=\"送信\"></form>");
              strcpy(command,"AT+CIPSEND=0,43\r\n");
              Serial1.print(command);
              getReply( 2000 );       
              Serial1.print(html);
              getReply( 2000 );   
   
              
 
            strcpy(html,"</body></html>");
            strcpy(command,"AT+CIPSEND=0,14\r\n");
            Serial1.print(command);
            getReply( 2000 ); 
            Serial1.print(html);
            getReply( 2000 ); 
            Serial1.print( "AT+CIPCLOSE=0\r\n" );
            getReply( 1500 ); 
 
          } // if(espSerial.find("+IPD"))
      } //if(espSerial.available())
 
      for (int i=0; i<3 ;i++)
      {LED[i]=NULL;}
      delay (100);
 
      // 次のリクエストを待つためにここにドロップします。
}
- 
ステップ 1 上記のように PlatformIO Arduino フレームワークを作成し、このコードをコピーしてコンパイルします。DFU ツールを使用してボードにダウンロードしてください。
 - 
ステップ 2 Mobaxterm のようなシリアルアシスタントを使用し、正しいボーレートとシリアルポートを設定します。
 - 
ステップ 3 リセットボタンを押すと、シリアルアシスタントに「AT コマンド」が表示されます。
 - 
ステップ 4 「AT+CIPSERVER=1,80」が表示された後、ESP8266 の IP アドレスをウェブサイトのアドレスとして設定し、開いてください。シリアルが「AT+CIPCLOSE=0」を表示した後、オンボード LED を制御するウェブサイトが表示されます。
 

- ステップ 5 「on」または「off」と入力して送信すると、オンボードのユーザー LED がオンまたはオフになります。LED の状態がウェブサイトに表示され、オンボード LED がその状態に従います。
 


リソース
- [PDF] GD32VF103_Datasheet_Rev1.0
 - [PDF] GD32VF103_User_Manual_EN_V1.0
 - [Zip] DFU Tool
 
技術サポート & 製品ディスカッション
技術的な問題がある場合は、フォーラムに問題を投稿してください。 弊社製品をお選びいただきありがとうございます!製品の使用体験がスムーズになるよう、さまざまなサポートを提供しています。異なる好みやニーズに対応するため、いくつかのコミュニケーションチャネルを用意しています。




