STM32duinoでAJAX制御してみました BluePill篇

最終更新2019年9月1日

スケッチは以下の通りです

/*
 * 20190320 TEST AJAX On BluePill
 * MEGA2560で動作していたコードをSTM32に移植し知識習得中
 * 
 * 出力8ch        PB4/PB3/PA15/PA10/PA9/PA8/PB15/PB14     
 *              ※PA11/PA12はUSBポートに割り当てられているため割り当ててはいけない
 *              ※PB6/PB7はI2Cに割り当てられているので割り当てるのを避ける
 *              ※PA4/PA5/PA6/PA7はSPIに割り当てられているので割り当てるのを避ける
 *              
 *
 */
#include <SPI.h>
#include <Ethernet3.h>
#define HttpPort        80
#define W550io_Rst      PB9             //BluePill
#define SPI1_NSS_PIN    PA4             //SPI_1 Chip Select pin is PA4. You can change it to the STM32 pin you want.
#define SPI2_NSS_PIN    PB12            //SPI_2 Chip Select pin is PB12. You can change it to the STM32 pin you want.
#define LED     PC13
#define LED1    PB4
#define LED2    PB3
#define LED3    PA15
#define LED4    PA10
#define LED5    PA9
#define LED6    PA8
#define LED7    PB15
#define LED8    PB14
#define SW1     PB0
#define SW2     PB1
#define SW3     PB10
#define SW4     PB11
#define AI1     PA0
#define AI2     PA1
#define AI3     PA2
#define AI4     PA3
//----------------------- VARIABLES LED ------------------------//
byte mac[]              = {0x00,0x50,0xC2,0x97,0x2C,0x3D};
byte ip[]               = {192, 168, 0, 200};
byte dns_server[]       = {192, 168, 0, 1};
byte gateway[]          = {0, 0, 0, 0};
byte subnet[]           = {255, 255, 255, 0};
int dout[9]     ={1,1,1,1,1,1,1,1,1};   // 1 で消灯 0で点灯
int din[4]      ={0,0,0,0};             // 1 =High
int ai[4]       ={0,0,0,0};             // STM32は12bit 0-4095
EthernetServer server(HttpPort);
String HTTP_req;                        // stores the HTTP request
void setup()
{
        Serial.begin(115200);           // for diagnostics
        Serial.println(F("Start"));
        SPI.begin();                    //Initialize the SPI_1 port.
        SPI.setBitOrder(MSBFIRST);      // Set the SPI_1 bit order
        SPI.setDataMode(SPI_MODE0);     //Set the  SPI_2 data mode 0
        SPI.setClockDivider(SPI_CLOCK_DIV8);   // Slow speed (72 / 16 = 4.5 MHz SPI_1 speed)
        pinMode(SPI1_NSS_PIN, OUTPUT);
/*       
        // Setup SPI 2
        SPI_2.begin(); //Initialize the SPI_2 port.
        SPI_2.setBitOrder(MSBFIRST); // Set the SPI_2 bit order
        SPI_2.setDataMode(SPI_MODE0); //Set the  SPI_2 data mode 0
        SPI_2.setClockDivider(SPI_CLOCK_DIV16);  // Use a different speed to SPI 1
        pinMode(SPI2_NSS_PIN, OUTPUT);
*/
        //Ethernet3で使用可能なAPI
        Ethernet.setCsPin(SPI1_NSS_PIN);
        Ethernet.setRstPin(W550io_Rst);
        //リセット処理
        pinMode(W550io_Rst, OUTPUT);
        digitalWrite(W550io_Rst, LOW);
        delay(10);
        digitalWrite(W550io_Rst, HIGH);
        Ethernet.begin(mac, ip);        // initialize Ethernet device
        server.begin();                 // start to listen for clients
        pinMode(LED,  OUTPUT);digitalWrite(LED, dout[0]);
        pinMode(LED1, OUTPUT);digitalWrite(LED1,dout[1]);
        pinMode(LED2, OUTPUT);digitalWrite(LED2,dout[2]);
        pinMode(LED3, OUTPUT);digitalWrite(LED3,dout[3]);
        pinMode(LED4, OUTPUT);digitalWrite(LED4,dout[4]);
        pinMode(LED5, OUTPUT);digitalWrite(LED5,dout[5]);
        pinMode(LED6, OUTPUT);digitalWrite(LED6,dout[6]);
        pinMode(LED7, OUTPUT);digitalWrite(LED7,dout[7]);
        pinMode(LED8, OUTPUT);digitalWrite(LED8,dout[8]);
        //digitalWrite(PA11,true);点灯してしまうのを避けたかったがダメだった
        //digitalWrite(PA12,true);点灯してしまうのを避けたかったがダメだった
        pinMode(SW1, INPUT_PULLUP);din[0]  = digitalRead(SW1);
        pinMode(SW2, INPUT_PULLUP);din[1]  = digitalRead(SW2);
        pinMode(SW3, INPUT_PULLUP);din[2]  = digitalRead(SW3);
        pinMode(SW4, INPUT_PULLUP);din[3]  = digitalRead(SW4);        
        ai[0]  = analogRead(AI1);
        ai[1]  = analogRead(AI2);
        ai[2]  = analogRead(AI3);
        ai[3]  = analogRead(AI4);
        Serial.print(F("SW1="));Serial.print(din[0]);Serial.print(F(" "));
        Serial.print(F("SW2="));Serial.print(din[1]);Serial.print(F(" "));
        Serial.print(F("SW3="));Serial.print(din[2]);Serial.print(F(" "));
        Serial.print(F("SW4="));Serial.println(din[3]);
        Serial.print(F("AI1="));Serial.print(ai[0]);Serial.print(F(" "));
        Serial.print(F("AI2="));Serial.print(ai[1]);Serial.print(F(" "));
        Serial.print(F("AI3="));Serial.print(ai[2]);Serial.print(F(" "));
        Serial.print(F("AI4="));Serial.println(ai[3]);
        
        Serial.print(F("server is at "));Serial.println(Ethernet.localIP());
}
long int count =0;
void loop()
{
        /*
        if ((count++ % 100) == 0){
                Serial.println(F("."));
        }else{
                Serial.print(F("."));
        }
        */
      
        EthernetClient client = server.available();             // try to get client
         if (client) {  // got client?
                boolean currentLineIsBlank = true;
                while (client.connected()) {
                        if (client.available()) {               // client data available to read
                                char c = client.read();         // read 1 byte (character) from client
                                HTTP_req += c;                  // save the HTTP request 1 char at a time
                                // 改行コードか空行を受けたら返信
                                if (c == '\n' && currentLineIsBlank) {
                                        // send a standard http response header
                                        // 標準のhttp応答ヘッダーを送信する
                                        Serial.print(F("PreCheck: "));Serial.println(HTTP_req);
                                        sendHttpResponseOk(client);
                                        // AJAX request for switch state
                                        if (HTTP_req.indexOf('?')>0) {
                                                // read switch state and send appropriate paragraph text
                                                Serial.println(HTTP_req);
                                                XMLhttpObjectAccess(client,HTTP_req);
                                                HTTP_req = "";
                                        }else{  // HTTP request for web page
                                                normalHttpAccess(client);
                                        }
                                        // display received HTTP request on serial port
                                        //Serial.print(HTTP_req);
                                        //HTTP_req = "";            // finished with request, empty string
                                        break;
                                }
                                // every line of text received from the client ends with \r\n
                                if (c == '\n') {
                                        // last character on line of received text
                                        // starting new line with next character read
                                        currentLineIsBlank = true;
                                } else if (c != '\r') {
                                        // a text character was received from client
                                        currentLineIsBlank = false;
                                }
                        } // end if (client.available())
                } // end while (client.connected())
                delay(1);      // give the web browser time to receive the data
                client.stop(); // close the connection
        } // end if (client)
        delay(1);
}
//--------------------------------------------------------------------------------------------------------
// 200 OK means the resource was located on the server and the browser (or service consumer) should expect a happy response
void sendHttpResponseOk(EthernetClient client)
{
        Serial.println(F("200 OK"));
        Serial.println();
  
        // send a standard http response header
        client.println(F("HTTP/1.1 200 OK"));
        client.println(F("Content-Type: text/html"));
        client.println(F("Connnection: close"));                        // do not reuse connection
        client.println();
}
//--------------------------------------------------------------------------------------------------------
// 404 means it ain't here. quit asking.
void sendHttp404(EthernetClient client)
{
        Serial.println(F("404 Not Found"));
        Serial.println();
  
        client.println(F("HTTP/1.1 404 Not Found"));
        client.println(F("Content-Type: text/html"));
        client.println(F("Connnection: close"));                        // do not reuse connection
        client.println();
}
//--------------------------------------------------------------------------------------------------------
//normal HTTP access
void normalHttpAccess(EthernetClient client)
{
        sendHttpResponseOk;
        client.println(F("<!doctype html>"));        
        client.println(F("<html lang='ja'>\n\t<head>\n\t\t<title>STM32duino Ajax TEST</title>\n"));
        client.println(F("\t\t<meta charset='UTF-8' name='viewport' content='width=240px' />\n"));
        client.println(F("\t\t<script type='text/javascript'>\n"));
        
        client.println(F("\t\tfunction createXMLHttpRequest(cbFunc){\n"));
        client.println(F("\t\t\tvar XObj = new XMLHttpRequest();\n"));
        client.println(F("\t\t\tif(XObj) XObj.onreadystatechange = cbFunc;return XObj;\n\t\t}\n"));
        client.println(F("\t\tfunction setData(val){\n\t\t\thtObj = createXMLHttpRequest(displayData);\n"));
        client.println(F("\t\t\tif(htObj){\n\t\t\t\thtObj.open('GET','/?btn='+val,true);htObj.send(null);\n\t\t\t}\n\t\t}\n"));
        client.println(F("\t\tfunction getData(){\n\t\t\thtObj = createXMLHttpRequest(displayData);\n"));
        client.println(F("\t\t\tif(htObj){\n\t\t\t\thtObj.open('GET','/?=',true);htObj.send(null);\n\t\t\t}\n\t\t}\n"));
        client.println(F("\t\tfunction displayData(){\n\t\t\tif((htObj.readyState == 4) && (htObj.status == 200)){\n"));
        client.println(F("\t\t\tdocument.getElementById('result').innerHTML =  htObj.responseText;\n\t\t\t}\n\t\t}\n"));
        client.println(F("\t\tfunction strT(){\n\t\t\tgetData(); timerID=setTimeout('strT()',document.getElementById('tf1').value);\n")); 
        client.println(F("\t\t\tdocument.getElementById('btn100').value = 'STARTING';\n\t\t}\n"));
        client.println(F("\t\tfunction clrT(){\n\t\t\tclearTimeout(timerID);\n"));
        client.println(F("\t\t\tdocument.getElementById('btn100').value = 'START';\n\t\t}\n"));
//        client.println(F("\t\t.myButton {\n\t\t\tbackground-color:#44c767;\n\t\t\t-moz-border-radius:28px;\n"));
//        client.println(F("\t\t\t-webkit-border-radius:28px;\n\t\t\tborder-radius:28px;\n\t\t\tborder:1px solid #18ab29;\n"));
//        client.println(F("\t\t\tdisplay:inline-block;\n\t\t\tcursor:pointer;\n\t\t\tcolor:#ffffff;\n"));
//        client.println(F("\t\t\tfont-family:Arial;\n\t\t\tfont-size:17px;\n\t\t\tpadding:16px 31px;\n"));
//        client.println(F("\t\t\ttext-decoration:none;\n\t\t\ttext-shadow:0px 1px 0px #2f6627;\n\t\t}\n"));
//        client.println(F("\t\t.myButton:hover {\n\t\t\tbackground-color:#5cbf2a;\n\t\t}\n"));
//        client.println(F("\t\t.myButton:active {\n\t\t\tposition:relative;\n\t\t\ttop:1px;\n\t\t}\n"));
        client.println(F("\t\t</script>\n\t</head>\n\t<body onLoad='getData()'>\n"));
        client.println(F("\t\t<h2 class='text-center'>STM32Duino AJAX TEST</h2>\n\t\t<form action='/' method='GET'><br />\n"));
        client.println(F("\t\t<input id='btn0' type='button' value=' PB4 ' onClick='setData(1)'>\n"));
        client.println(F("\t\t<input id='btn1' type='button' value=' PB3 ' onClick='setData(2)'>\n"));
        client.println(F("\t\t<input id='btn2' type='button' value=' PA15 ' onClick='setData(3)'>\n"));
        client.println(F("\t\t<input id='btn3' type='button' value=' PA10 ' onClick='setData(4)'><br />\n"));
        client.println(F("\t\t<input id='btn4' type='button' value=' PA9 ' onClick='setData(5)'>\n"));        
        client.println(F("\t\t<input id='btn5' type='button' value=' PA8 ' onClick='setData(6)'>\n"));
        client.println(F("\t\t<input id='btn6' type='button' value=' PB15 ' onClick='setData(7)'>\n"));
        client.println(F("\t\t<input id='btn7' type='button' value=' PB14 ' onClick='setData(8)'><br />\n\t\t</form>\n"));
//        client.println(F("\t\t<a href='#1' class='myButton1'>SW1</a>\n"));
//        client.println(F("\t\t<a href='#2' class='myButton2'>SW2</a>\n"));
//        client.println(F("\t\t<a href='#3' class='myButton3'>SW3</a>\n"));
//        client.println(F("\t\t<a href='#4' class='myButton4'>SW4</a>\n"));
        client.println(F("\t\t<div class='form-group'>\n\t\t\t<label for='AI0'>AI0(0-4095)</label>\n"));
        client.println(F("\t\t\t<input id='AI0' type='range' class='form-control-range' min='0' max='4095' value='0'>\n\t\t</div>\n"));
        client.println(F("\t\t<div class='form-group'>\n\t\t\t<label for='AI1'>AI1(0-4095)</label>\n"));
        client.println(F("\t\t\t<input id='AI1' type='range' class='form-control-range' min='0' max='4095' value='0'>\n\t\t</div>\n"));
        client.println(F("\t\t<div class='form-group'>\n\t\t\t<label for='AI2'>AI2(0-4095)</label>\n"));
        client.println(F("\t\t\t<input id='AI2' type='range' class='form-control-range' min='0' max='4095' value='0'>\n\t\t</div>\n"));
        client.println(F("\t\t<div class='form-group'>\n\t\t\t<label for='AI3'>AI3(0-4095)</label>\n"));
        client.println(F("\t\t\t<input id='AI3' type='range' class='form-control-range' min='0' max='4095' value='0'>\n\t\t</div>\n"));
        client.println(F("\t\t<form>\n\t\t<input id='btn100' type='button' value=' START ' onClick='strT()'>\n"));
        client.println(F("\t\t<input id='btn200' type='button' value=' STOP ' onClick='clrT()'>\n"));
        client.println(F("\t\t<input id='tf1' type='text' size='6' value='1000'>\n"));
        client.println(F("\t\t</form><br />\n\t\t<div id='result'></div><br />\n"));
        client.println(F("\t</body>\n</html>"));
}
//--------------------------------------------------------------------------------------------------------
//using XMLhttpObject access
void XMLhttpObjectAccess(EthernetClient client,String parm)
{
        Serial.print(F("XML:"));Serial.println(parm);
        int check = parm.indexOf('=');
        if(check != -1){
                //Set Digital Port
                int check2 = parm.indexOf('btn');
                if(check2 != -1){
                        int port = (parm.substring(check+1)).toInt();
                        Serial.print(F("Port="));Serial.println(port);
                        dout[port] = !dout[port];
                        switch(port){
                                case 0:
                                        digitalWrite(LED, dout[port]);
                                        break;
                                case 1:
                                        digitalWrite(LED1, dout[port]);
                                        break;
                                case 2:
                                        digitalWrite(LED2, dout[port]);
                                        break;
                                case 3:
                                        digitalWrite(LED3, dout[port]);
                                        break;
                                case 4:
                                        digitalWrite(LED4, dout[port]);
                                        break;
                                case 5:
                                        digitalWrite(LED5, dout[port]);
                                        break;
                                case 6:
                                        digitalWrite(LED6, dout[port]);
                                        break;
                                case 7:
                                        digitalWrite(LED7, dout[port]);
                                        break;
                                case 8:
                                        digitalWrite(LED8, dout[port]);
                                        break;
                                default:
                                        break;
                                      
                        }
                }
                //Write JSONP Data (Digital & Analog Ports Status, Callback function name is 'cb')
                client.print(F("cb({DO:["));
                for(int i=0; i<9; i++ ){
                        client.print(dout[i]);
                        if(i<8){
                                client.print(F(","));
                        }
                }
                client.print(F("],DI:["));
                client.print(digitalRead(SW1));client.print(F(","));
                client.print(digitalRead(SW2));client.print(F(","));
                client.print(digitalRead(SW3));client.print(F(","));
                client.print(digitalRead(SW4));client.print(F("]"));
                client.print(F(",AI:["));
                client.print(analogRead(AI1));client.print(F(","));
                client.print(analogRead(AI2));client.print(F(","));
                client.print(analogRead(AI3));client.print(F(","));
                client.print(analogRead(AI4));client.print(F("]"));
                //client.print(F("],TIME:["));
                //now = RTC.now();
                //outDateTime = (long int)now.hour() * 10000 + now.minute() * 100 + now.second();
                //Serial.print(F("Time: "));Serial.println(outDateTime);
                //Serial.print(F("Time: "));Serial.print(now.hour());Serial.print(F(":"));
                //Serial.print(now.minute());Serial.print(F(":"));Serial.println(now.second());
                //client.print(outDateTime);
                //client.print(now.hour());client.print(F(":"));
                //client.print(now.minute());client.print(F(":"));client.println(now.second());
                //client.print("]});");
        }
}

上記スケッチにはブラウザに送るHTMLのコードが含まれています。実際にブラウザで読み込んでコードを確認すればいいのですが一応示します。

<!doctype html>
<html lang='ja'>
	<head>
		<title>STM32duino Ajax TEST</title>
		<meta charset='UTF-8' name='viewport' content='width=240px' />
		<script type='text/javascript'>
		function createXMLHttpRequest(cbFunc){
			var XObj = new XMLHttpRequest();
			if(XObj) XObj.onreadystatechange = cbFunc;return XObj;
		}
		function setData(val){
			htObj = createXMLHttpRequest(displayData);
			if(htObj){
				htObj.open('GET','/?btn='+val,true);htObj.send(null);
			}
		}
		function getData(){
			htObj = createXMLHttpRequest(displayData);
			if(htObj){
				htObj.open('GET','/?=',true);htObj.send(null);
			}
		}
		function displayData(){
			if((htObj.readyState == 4) && (htObj.status == 200)){
			document.getElementById('result').innerHTML =  htObj.responseText;
			}
		}
		function strT(){
			getData(); timerID=setTimeout('strT()',document.getElementById('tf1').value);
			document.getElementById('btn100').value = 'STARTING';
		}
		function clrT(){
			clearTimeout(timerID);
			document.getElementById('btn100').value = 'START';
		}
		</script>
	</head>
	<body onLoad='getData()'>
		<h2 class='text-center'>STM32Duino AJAX TEST</h2>
		<form action='/' method='GET'><br />
		<input id='btn0' type='button' value=' PB4 ' onClick='setData(1)'>
		<input id='btn1' type='button' value=' PB3 ' onClick='setData(2)'>
		<input id='btn2' type='button' value=' PA15 ' onClick='setData(3)'>
		<input id='btn3' type='button' value=' PA10 ' onClick='setData(4)'><br />
		<input id='btn4' type='button' value=' PA9 ' onClick='setData(5)'>
		<input id='btn5' type='button' value=' PA8 ' onClick='setData(6)'>
		<input id='btn6' type='button' value=' PB15 ' onClick='setData(7)'>
		<input id='btn7' type='button' value=' PB14 ' onClick='setData(8)'><br />
		</form>
		<div class='form-group'>
			<label for='AI0'>AI0(0-4095)</label>
			<input id='AI0' type='range' class='form-control-range' min='0' max='4095' value='0'>
		</div>
		<div class='form-group'>
			<label for='AI1'>AI1(0-4095)</label>
			<input id='AI1' type='range' class='form-control-range' min='0' max='4095' value='0'>
		</div>
		<div class='form-group'>
			<label for='AI2'>AI2(0-4095)</label>
			<input id='AI2' type='range' class='form-control-range' min='0' max='4095' value='0'>
		</div>
		<div class='form-group'>
			<label for='AI3'>AI3(0-4095)</label>
			<input id='AI3' type='range' class='form-control-range' min='0' max='4095' value='0'>
		</div>
		<form>
		<input id='btn100' type='button' value=' START ' onClick='strT()'>
		<input id='btn200' type='button' value=' STOP ' onClick='clrT()'>
		<input id='tf1' type='text' size='6' value='1000'>
		</form><br />
		<div id='result'></div><br />
	</body>
</html>



Webの方法としてAJAXを検討しましたが、MODBUSによる制御も検討したいです。


戯言(nonsense)に戻る


問い合わせ頁の表示


免責事項

本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。

本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。

商標・登録商標

Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。