最終更新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>
- SPIのクロックを1/4 つまり18MHzに設定しています。反応は良くなっていると思います。
- メモリに対する余裕があります。コード自体は50%程度使いますが実行時RAMは30%に満たないようです。
Webの方法としてAJAXを検討しましたが、MODBUSによる制御も検討したいです。
免責事項
本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。本ソフトウエアの著作権は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社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。